Symfony2 nyelvválasztás

A nyelvválasztást fogjuk most megnézni symfony2-ben.

Állítsuk be a következőket:

app/config/config.yml:
     translator: { fallbacks: [hu] }

Alapértelmezetten magyarra állítjuk:
app/config/parameters.yml:
     locale: hu

Nyelvi fájlok helye pl: \src\Web\BlogBundle\Resources\translations\messages.hu.xlf
Annyi fájlt kell csinálni amennyi nyelvet szeretnénk, a tartalmuk:
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="hu" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>Home</source>
                <target>Kezdőoldal</target>
            </trans-unit>	
            <trans-unit id="2">
                <source>Search</source>
                <target>Keresés</target>
            </trans-unit>
        </body>
    </file>
</xliff>

A source lesz az azonosító amire hivatkozunk, a target a lefordított szöveg. Értelemszerűen a többi nyelven is ugyanígy néznek ki a fájlok csak a target és a source-langugae értékét változtatjuk meg.

Konzolból meg tudjuk nézni, hogy jól töltöttük-e ki a fájlokat, egy szép táblázatot fogunk kapni:
# php app/console debug:translation hu WebBlogBundle

A beállított szövegeket a view-okben a következő képpen tudjuk használni a twig-ben:
 
{{ 'Home'|trans }}

Itt a 'Home' azonosítóval rendelkező szöveget fogja megjeleníteni az oldalunkon.

Ha esetleg szeretnénk ellenőrizni, hogy melyik nyelv az aktuális akkor a következőt írjuk a view-ban:
 
lang: {{ app.request.locale }}     session: {{ app.session.get('_locale') }}    

Szeretnénk, hogy legyenek gombok/linkek is amikre kattintva változtathatjuk a nyelvet. Készítsük el a linkeket hozzá:
 
<ul class="lang-menu">
  <li><a href="{{ path('changeLanguage',{'changeToLocale':'hu'}) }}">Hungarian</a></li>
  <li><a href="{{ path('changeLanguage',{'changeToLocale':'en'}) }}">English</a></li>
</ul>

A controllerbe csináljunk egy metódust:
 
    /** from Controller
    *
    * @Route("/changeLanguage/{changeToLocale}", name="changeLanguage")
    *
    */
    public function changeLanguageAction($changeToLocale){
        $this->get('request')->attributes->set('_locale', null);
        $this->get('session')->set('_locale', $changeToLocale);

        return $this->redirect($this->generateUrl('main'));
    }  
 
A routing.yml-be is jegyezzük be a metódust:
changeLanguage:
    path:    /changeLanguage/{changeToLocale}
    defaults: { _controller: WebBlogBundle:News:changeLanguage }

Most már a linkek megtudják hívni a controllert és a metudóst. Valójában a következő linkek hívódnak meg:
http://localhost/symfony2/web/app_dev.php/changeLanguage/en
http://localhost/symfony2/web/app_dev.php/changeLanguage/hu

Szükségünk van egy eseménykezelőre, ehhez hozzunk létre egy EventListener mappát, majd abban egy LocalListener.php fájlt a tartalma:
 
<?php
// src/Web/BlogBundle/EventListener/LocaleListener.php
namespace Web\BlogBundle\EventListener;

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

class LocaleListener implements EventSubscriberInterface
{
    private $defaultLocale;

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

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

        // try to see if the locale has been set as a _locale routing parameter
        if ($locale = $request->attributes->get('_locale')) {
            $request->getSession()->set('_locale', $locale);
        } else {
            // if no explicit locale has been set on this request, use one from the session
            $request->setLocale($request->getSession()->get('_locale', $this->defaultLocale));
        }
    }

    public static function getSubscribedEvents()
    {
        return array(
            // must be registered before the default Locale listener
            KernelEvents::REQUEST => array(array('onKernelRequest', 17)),
        );
    }
}

Ezután az app/config/service.yml fájlba írjuk a következőket:
    app.locale_listener:
        class: Web\BlogBundle\EventListener\LocaleListener
        arguments: ["%kernel.default_locale%"]
        tags:
            - { name: kernel.event_subscriber }
Ez után már működnie kell a fordításnak.

Ezt csak úgy példaként írom még ide, hogyha a controllerben szeretnénk ellenőrizni, hogy milyen nyelvet használunk éppen, akkor a következő kódot használhatjuk:
    $locale = $request->getLocale();
    print "getlocal:"; print_r($locale);

Mi viszont nem csak statikus szöveget szeretnénk lefordítani. Én alapból már úgy terveztem meg az adatbázist, hogy ne csak egy title mező legyen hanem legyen pl titleHu és titleEn mező is, hogy letudjam tárolni az angol címet is. Értelemszerűen annyi mezőt veszünk fel ahány nyelvet szeretnénk és a tartalmat tároló mezőknél is így járunk el.

A controllerben kérdezzük le a local értékét és adjuk oda a repository-t meghívó metódusnak pl:
	$locale = $request->getLocale();

	$entities = $em->getRepository('WebBlogBundle:News')->getNewsMain($locale);

 A repository-ban csak annyit csináltam, hogy a select paramétereit változtatom attól függően, hogy milyen nyelven történik a lekérdezés. Itt egy rövid kevésbé életszerű példa:
public function getNewsMain($locale)
    {		
		if($locale=="en"){ // english
			$select="n.titleEn AS titlehu g.groupName AS groupname";			
		}
		else{ // only hungary
			$select="n.titleHu AS titlehu, g.groupName AS groupname";
		}
		
		$entities = $this->createQueryBuilder('n')
			->select($select)
			->join('n.group','g')
 			->where('g.groupName = :group')
			->setParameter('group','teszt')
			->getQuery()->getResult();
		
		return $entities;
    } 	
 
Most már az adatbázisból is az aktuálisan kiválasztott nyelven fog megjelenni az oldal.

Olvasnivaló:
http://symfony.com/doc/current/book/translation.html
http://symfony.com/doc/current/cookbook/session/locale_sticky_session.htm
2015.08.30.