04/02/2017 - SYMFONY
Bu örnekte symfony ile çok dilli uygulama yapmayı öğreneceğiz. İngilizce en
ve Türkçe tr
dillerinde sabit ve değişken mesajlar kullanacağız. Mesaj kodlarını insanların okuyabilecekleri mesajlara çevirmek için, twig şablonlarında trans
fonksiyonunu, controller içinde ise translator
servisini kullanacağız.
Yaptığınız değişikliklerden sonra, sık sık önbelleği temizlemeniz gerekecek. Bu tüm ortamlar için geçerlidir.
Kullanımda olan InanzzzApplicationBundle
paketindeki en
dili için mevcut olan tüm mesajları $ php bin/console debug:translation en InanzzzApplicationBundle
komutu ile listeleyebilirsiniz.
Aşağıda da gördüğümüz gibi URL en
ve tr
parametrelerini kullanıyor.
http://myapp.dev/app_dev.php/en/
http://myapp.dev/app_dev.php/tr/
http://myapp.dev/app_dev.php/en/translator
http://myapp.dev/app_dev.php/tr/translator
Her URL _locale
parametresini en
veya tr
olarak barındırmak zorundadır. Eğer bir kullanıcı içinde en
veya tr
parametresi olmayan bir URL'ye ulaşmaya çalışırsa, event listener isteğin yolunu kesip en
veya tr
ekleme işlemini yapıp, kullanıcı yönlendirme işlemini yapacaktır. Birazdan bu işlemin nasıl yapıldığını göreceksiniz.
parameters:
locale: en
default_locale: en
valid_locales: en|tr
framework:
translator: { fallbacks: ["%locale%"] }
inanzzz_application:
resource: "@InanzzzApplicationBundle/Controller/"
type: annotation
prefix: /{_locale}/
requirements:
_locale: "%valid_locales%"
defaults:
_locale: "%default_locale%"
_wdt:
resource: "@WebProfilerBundle/Resources/config/routing/wdt.xml"
prefix: /{_locale}/_wdt
_profiler:
resource: "@WebProfilerBundle/Resources/config/routing/profiler.xml"
prefix: /{_locale}/_profiler
_errors:
resource: "@TwigBundle/Resources/config/routing/errors.xml"
prefix: /{_locale}/_error
_main:
resource: routing.yml
#src/Inanzzz/ApplicationBundle/Resources/translations/messages.en.xlf
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="en" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="application.greeting">
<source>application.greeting</source>
<target>Welcome to our multilingual application!</target>
</trans-unit>
<trans-unit id="user.greeting">
<source>user.greeting</source>
<target>Hello %name% %surname%!</target>
</trans-unit>
<trans-unit id="page.translator.header">
<source>page.translator.header</source>
<target>Translator</target>
</trans-unit>
</body>
</file>
</xliff>
$ php bin/console debug:translation en InanzzzApplicationBundle
---------- ---------- ------------------------ ------------------------------------------
State Domain Id Message Preview (en)
---------- ---------- ------------------------ ------------------------------------------
messages application.greeting Welcome to our multilingual application!
unused messages user.greeting Hello %name% %surname%!
unused messages page.translator.header Translator
---------- ---------- ------------------------ ------------------------------------------
#src/Inanzzz/ApplicationBundle/Resources/translations/messages.tr.xlf
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file source-language="tr" datatype="plaintext" original="file.ext">
<body>
<trans-unit id="application.greeting">
<source>application.greeting</source>
<target>Çok dilli web uygulamamıza hoşgeldiniz!</target>
</trans-unit>
<trans-unit id="user.greeting">
<source>user.greeting</source>
<target>Merhabe %name% %surname%!</target>
</trans-unit>
<trans-unit id="page.translator.header">
<source>page.translator.header</source>
<target>Çevirmen</target>
</trans-unit>
</body>
</file>
</xliff>
$ php bin/console debug:translation tr InanzzzApplicationBundle
---------- ---------- ------------------------ -----------------------------------------
State Domain Id Message Preview (tr)
---------- ---------- ------------------------ -----------------------------------------
messages application.greeting Çok dilli web uygulamamıza hoşgeldiniz!
unused messages user.greeting Merhabe %name% %surname%!
unused messages page.translator.header Çevirmen
---------- ---------- ------------------------ -----------------------------------------
namespace Inanzzz\ApplicationBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
/**
* @Route("", service="inanzzz_application.controller.default")
*/
class DefaultController
{
private $templating;
public function __construct(EngineInterface $templating)
{
$this->templating = $templating;
}
/**
* @Method({"GET"})
* @Route("/")
*
* @return Response
*/
public function indexAction()
{
return $this->templating->renderResponse(
'InanzzzApplicationBundle:Default:index.html.twig'
);
}
}
namespace Inanzzz\ApplicationBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Translation\TranslatorInterface;
/**
* @Route("/translator", service="inanzzz_application.controller.translator")
*/
class TranslatorController
{
private $templating;
private $translator;
public function __construct(
EngineInterface $templating,
TranslatorInterface $translator
) {
$this->templating = $templating;
$this->translator = $translator;
}
/**
* @Method({"GET"})
* @Route("/")
*
* @return Response
*/
public function indexAction()
{
return $this->templating->renderResponse(
'InanzzzApplicationBundle:Translator:index.html.twig',
[
'page_header' => $this->translator->trans('page.translator.header'),
'user_greeting' => $this->translator->trans(
'user.greeting',
[
'%name%' => 'Inanzzz',
'%surname%' => 'Zzznani',
]
)
]
);
}
}
services:
inanzzz_application.controller.default:
class: Inanzzz\ApplicationBundle\Controller\DefaultController
arguments:
- '@templating'
inanzzz_application.controller.translator:
class: Inanzzz\ApplicationBundle\Controller\TranslatorController
arguments:
- '@templating'
- '@translator'
#src/Inanzzz/ApplicationBundle/Resources/views/Default/index.html.twig
{% extends '::base.html.twig' %}
{% block body %}
<h3>{{ 'application.greeting'|trans }}</h3>
{% endblock %}
#src/Inanzzz/ApplicationBundle/Resources/views/Translator/index.html.twig
{% extends '::base.html.twig' %}
{% block body %}
<h3>{{ page_header }}</h3>
<p>{{ user_greeting }}</p>
{% endblock %}
Eğer URL içinde en
veya tr
yoksa, uygulama 404 NotFoundHttpException
hatası verecektir. Bu gibi durumlarda event listener devreye girip, aşağıdaki işlemleri yapacaktır.
NotFoundHttpException
hatasını yakalar.en
ve tr
parametrelerinin eksik olup olmadığını kontrol eder.en
veya tr
) onu kullanır, değilse uygulamanın varsayılan dilini (en
) kullanır.en
veya tr
) parçalanan URL'nin başına ekler.Eğer URL içinde en
veya tr
varsa ve de uygulama 404 NotFoundHttpException
hatası veriyorsa, event listener hiçbir şey olmamış gibi davranır çünkü, kullanıcı mevcut olmayan bir sayfaya ulaşmak istiyor demektir ki bu da normal birşeydir.
namespace Inanzzz\ApplicationBundle\EventListener;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class LocaleRedirectListener
{
private $validLocales;
public function __construct($validLocales)
{
$this->validLocales = explode('|', $validLocales);
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
// 1
if (!$event->getException() instanceof NotFoundHttpException) {
return;
}
// 2
if ($event->getRequestType() != HttpKernelInterface::MASTER_REQUEST) {
return;
}
// 3
$request = $event->getRequest();
$uriParts = explode('/', $request->getPathInfo());
// 4
if ($this->isLocaleMissing($uriParts)) {
// 5
$response = new RedirectResponse($this->constructRedirectUri($request));
// 6
$event->setResponse($response);
}
}
private function isLocaleMissing(array $uriParts)
{
return !isset($uriParts[1]) || !$uriParts[1] || !in_array($uriParts[1], $this->validLocales);
}
private function constructRedirectUri(Request $request)
{
// 5.1
$browserLanguage = $request->getPreferredLanguage($this->validLocales);
// 5.2
$locale = in_array($browserLanguage, $this->validLocales)
? $browserLanguage
: $request->getDefaultLocale();
// 5.3
$find = str_replace('/', '\/', $request->getPathInfo());
// 5.4
return preg_replace(
'/'.$find.'$/',
'/'.$locale.'/'.trim($request->getPathInfo(), '/'),
$request->getUri()
);
}
}
services:
inanzzz_application.listener.locale_redirect:
class: Inanzzz\ApplicationBundle\EventListener\LocaleRedirectListener
arguments:
- "%valid_locales%"
tags:
- { name: kernel.event_listener, event: kernel.exception, method: onKernelException }