Blog

ブログ

【ECCUBE4系】ボタンで表示言語を選択できるようにする

先日shopifyでサイトを多言語化する方法をご紹介させて頂きました。
本日は、ECCUBE4系で多言語化対応を行う際に、ボタンで言語を切り替えられるように実装してみたのでご紹介します。

まずはControllerの作成

<?php

namespace Customize\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;

class LanguageController extends AbstractController
{
    /**
    * @Route("change/language", name="language_change")
    */
    public function changeLanguage(Request $request)
    {
        $session = $request->getSession();
        $session->set('language', $request->query->get('language'));

        return $this->redirect(言語選択後に表示したいページ);
    }
}

これでボタンを押したときに、セッションに選択した言語情報を保持出来るようにしました。

 

header.twigに言語切り替えボタンを出力

{% if app.session.get('language') == 'ja" %}
  <ul>
    <li><a href="{{ url('language_change', {'language': 'en'}) }}">{{ 'English'|trans }}</a></li>
  </ul>
{% else %}
  <ul>
    <li><a href="{{ url('language_change', {'language': 'ja'}) }}">{{ '日本語'|trans }}</a></li>
  </ul>
{% endif %}

選択済みの言語によって、出力されるボタンが動的に変わるようにしました。
(初期値は、.envのECCUBE_LOCALEに設定されている値なので、「English」のボタンが初期値で出力されます)

EventSubscriberを作成する

ここが一番大好きな作業です!
みんな大好き、EventSubscriberです!

<?php 
namespace Customize\EventSubscriber; 

use Symfony\Component\DependencyInjection\ContainerInterface; 
use Symfony\Component\EventDispatcher\EventSubscriberInterface; 
use Symfony\Component\HttpKernel\Event\GetResponseEvent; 
use Symfony\Component\HttpKernel\KernelEvents; 

class LanguageSubscriber implements EventSubscriberInterface 
{ 
    /**
     * @var ContainerInterface
     */ private $container;

    /**
      * LanguageSubscriber constructor. 
       * 
       * @param ContainerInterface $container 
       */ 
       public function __construct(ContainerInterface $container)
      { 
                 $this->container = $container;
    }

    /**
     * @return array
     */
    public static function getSubscribedEvents()
    {
        return [
            KernelEvents::REQUEST => [['onKernelRequest', 18]],
        ];
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();

        $request->setLocale($request->getSession()->get('language', env('ECCUBE_LOCALE')));
    }
}

これで出来上がりです!
なんて簡単なんでしょう、EventSubscriber最高ですね!

最後に補足説明

ちなみに、KernelEvents::REQUESTで、2番目に指定している「18」ですが、これはSymfonyのPriority(優先順位)の指定になります。
ECCUBEもローカルで開発してる時なんかは、デバッグモードにしていると思いますが、デバッグバーをポチッとするとSymfonyの画面に遷移しますよね?

左のメニューバーから「Events」を選択すると、Event Dispatcherが確認できるので、
“Symfony\Component\HttpKernel\EventListener\LocaleListener::onKernelRequest()”
のPriorityが幾つになっているか確認して、LocaleListener::onKernelRequest()よりも優先順位を決めてあげるのが良さそうです。

優先順位まで指定できるなんて、EventSubscriber最高ですね!(2回目)
EventSubscriberが大好きすぎて、いろんな処理を割り込ませたくなりますが、他の処理を割り込ませた話は、またの機会に投稿しようと思います。

messages.XX.yamlやvalidators.XX.yamlの作成を忘れずに行ってくださいね!

Requestのお供に、EventSubscriberをぜひよろしくお願い致します。