melanjutkan tulisan saya sebelumnya tentang Translation di symfony 4, kali ini saya lanjutkan dengan translation di routing symfony. Contoh penggunaan translation di url adalah seperti url berikut : 


nah kira kira kita akan belajar membuat translation di url. 

Event

pertama kita buat folder baru bernama EventSubscriber di dalam folder src. Oh iya, bagi yang belum punya bahan untuk latihan kali ini, silahkan download di akun github saya di https://github.com/kematjaya0/tutorial atau silahkan baca ditulisan saya sebelumnya di https://catatan-pemrograman.blogspot.com/2018/10/menggunakan-translation-di-symfony-4.html

Kemudian buat file baru bernama LocaleRewriteListener,php yang implements class EventSubscriberInterface.php. Seperti pada kode berikut : 
<?php //src/EventSubscriber/LocaleRewriteListener.php

/**
* Description of LocaleRewriteListener
*
* @author NUR HIDAYAT
*/

namespace App\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class LocaleRewriteListener implements EventSubscriberInterface{

/**
* @var Symfony\Component\Routing\RouterInterface
*/
private $router;

/**
* @var routeCollection \Symfony\Component\Routing\RouteCollection
*/
private $routeCollection;

/**
* @var string
*/
private $defaultLocale;

/**
* @var array
*/
private $supportedLocales;

/**
* @var string
*/
private $localeRouteParam;

public function __construct(RouterInterface $router, $defaultLocale = 'id', array $supportedLocales = array(), $localeRouteParam = '_locale')
{
$this->router = $router;
$this->routeCollection = $router->getRouteCollection();
$this->defaultLocale = $defaultLocale;
$this->supportedLocales = $supportedLocales;
$this->localeRouteParam = $localeRouteParam;
}

public function isLocaleSupported($locale)
{
return in_array($locale, $this->supportedLocales);
}

public function onKernelRequest(GetResponseEvent $event) // function yang wajib ada di setiap class yang implements dari interface EventSubscriberInterface
{
$request = $event->getRequest(); // mengambil object Request
$path = $request->getPathInfo(); // mengambil path / url dari request

$route_exists = false; //by default assume route does not exist.

// check dari routing yang tersedia, apakah url ada atau tidak
foreach($this->routeCollection as $routeObject){
$routePath = $routeObject->getPath();
if($routePath == "/{_locale}".$path){
$route_exists = true;
break;
}
}

// jika path routing ada
if($route_exists == true){
$locale = $request->getPreferredLanguage(); // ambil bahasa

if($locale=="" || $this->isLocaleSupported($locale)==false){
$locale = $request->getDefaultLocale();
}

// set url dengan disertai bahasa
$event->setResponse(new RedirectResponse($request->getSchemeAndHttpHost().$request->getBaseUrl()."/".$locale.$path));
}
}

public static function getSubscribedEvents() // override function untuk setting prioritas class yang dijalankan terlebih dahulu
{
return array(
KernelEvents::REQUEST => array(array('onKernelRequest', 19)),
);
}
}

class di atas adalah Event Dispatcher yang digunakan untuk meredirect url / mereplace url yg masuk yang apabila url request tidak disertai dengan bahasa / locale, maka akan ditambahkan dengan bahasa / locale default dari aplikasi. Untuk pembahasan Event Dispatcher bisa disimak pada tulisan saya lain kali. Setiap class yang implements interface EventSubscriberInterface.php harus mempunyai function onKernelRequest() yang akan dijalankan saat terjadi request ke aplikasi. Kemudian tambahkan / daftarkan file Event Dispatcher kita di config service.yml.
    App\EventSubscriber\LocaleRewriteListener:
arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"]
tags:
- { name: kernel.event_subscriber }

dan tambahkan kode berikut di bagian parameters sehingga menjadi seperti berikut:
parameters:
locale: 'en'
    app_locales: en|id
locale_supported: ['en','id']

sehingga file service.yml kita menjadi seperti berikut :
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
    app_locales: en|id
locale_supported: ['en','id']

services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']

App\EventSubscriber\LocaleRewriteListener:
arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"]
tags:
- { name: kernel.event_subscriber }
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

kemudian buat lagi satu class bernama LocaleSubscriber.php di dalam folder src/EventSubscriber yang juga implement dari Interface Symfony\Component\EventDispatcher\EventSubscriberInterface.php seperti berikut:
<?php // src/EventSubscriber/LocaleSubscriber.php

/**
* Description of LocaleSubscriber
*
* @author NUR HIDAYAT
*/

namespace App\EventSubscriber;

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

class LocaleSubscriber implements EventSubscriberInterface{

private $defaultLocale;

public function __construct($defaultLocale = 'id')
{
$this->defaultLocale = $defaultLocale;
}


public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
if (!$request->hasPreviousSession()) {
return;
}

if ($locale = $request->attributes->get('_locale')) {
$request->getSession()->set('_locale', $locale);
}else{
$request->getSession()->set('_locale', $this->defaultLocale);
}
$request->setDefaultLocale($request->getSession()->get('_locale', $this->defaultLocale));
}

public static function getSubscribedEvents()
{
return array(
KernelEvents::REQUEST => array(array('onKernelRequest', 21)),
);
}
}

class diatas digunakan untuk menyimpan settingan bahasa yang diperoleh dari url dan disimpan ke session agar dapat digunakan ditempat lain seperti di Controller atau di template twig. Kemudian jangan lupa untuk menambahkannya di file services.yaml sehingga file config/services.yaml kita menjadi seperti berikut:
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.

# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices/configuration.html#application-related-configuration
parameters:
locale: 'en'
    app_locales: en|id
locale_supported: ['en','id']

services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
public: false # Allows optimizing the container by removing unused services; this also means
# fetching services directly from the container via $container->get() won't work.
# The best practice is to be explicit about your dependencies anyway.

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/*'
exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'

# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller'
tags: ['controller.service_arguments']

App\EventSubscriber\LocaleSubscriber:
arguments: ['%kernel.default_locale%']

App\EventSubscriber\LocaleRewriteListener:
arguments: ["@router", "%kernel.default_locale%", "%locale_supported%"]
tags:
- { name: kernel.event_subscriber }
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

nah kemudian untuk memeriksa apakah file kita berhasil di load / dijalankan, buka folder project kita di cmd kemudian jalankan perintah berikut:

php bin/console debug:event-dispatcher kernel.request

maka kira-kira akan muncul seperti ini:

nah, jika class tadi muncul di daftar tersebut seperti gambar di atas, maka kita berhasil menambahkannya sebagai event di symfony.

Routing

Sampai disini, kita sudah berhasil menambahkan Event di project symfony kita kemudian kita lanjutkan untuk konfigurasi routing. Kita buka file config/routes/annotations.yaml sehingga menjadi seperti berikut : 
controllers:
resource: ../../src/Controller/
type: annotation
prefix: /{_locale}
requirements:
_locale: '%app_locales%'
defaults:
_locale: '%locale%'

ini untuk memaksa pengguna / user untuk memasukkan kode negara di url. Untuk memeriksa daftar routing, jalankan perintah ini di CMD : 

php bin/console debug:router

sehigga muncul daftar seperti gambar berikut:

nah pada gambar di atas terlihat bahwa routing kita menjadi /{_locale}/ yang berarti user harus menyertakan kode negara untuk mengakses halaman web. Sekarang kita coba akses menggunakan POSTMAN:
pada contoh di atas, saya mencoba melakukan insert data dengan url disertai kode negara inggris : 

http://localhost:8000/en/api/test/insert

sehingga pesan yang keluar adalah bahasa inggris, sekarang kita coba POST data menggunakan url dengan kode id :

http://localhost:8000/id/api/test/insert

sehingga pesan yang keluar adalah bahasa indonesia seperti pada gambar berikut:

sekian dulu tulisan saya kali ini, semoga bermanfaat, dan lain kesempatan saya akan coba tulis tentang Service. Terima kasih

Catatan : Sorce Code Latihan dapat di unduh di github saya di https://github.com/kematjaya0/tutorial