Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony2 language selector

Tags:

php

symfony

I would like to integrate a simple HTML form allowing the user to change Symfony2 web application's language (i.e. from page en/faq go to fr/faq). How to do it in a proper way?

I have found a nice way of doing it with Symfony but not with Symfony2: http://symfony.com/blog/play-with-the-user-language

like image 329
cvsoftware Avatar asked Oct 07 '11 13:10

cvsoftware


2 Answers

The easiest way I have found is to do it directly in the twig template. At least, it works with 2.2:

<ul class="lang-menu">
  <li><a href="{{ path(app.request.get('_route'), app.request.get('_route_params')|merge({'_locale': 'ca'})) }}">Català</a></li>
  <li><a href="{{ path(app.request.get('_route'), app.request.get('_route_params')|merge({'_locale': 'en'})) }}">English</a></li>
</ul>
like image 173
Waiting for Dev... Avatar answered Oct 04 '22 21:10

Waiting for Dev...


You need to call $this->get('session')->setLocale($locale) (replace 'session' by 'request' for Symfony 2.1) inside your controller.

I've created a form, to which I pass an array of languages:

<?php
class LanguageType extends AbstractType
{
    public function buildForm(FormBuilder $builder, array $options)
    {
        $langs = $options['languages'];
        $langs = array_combine($langs, $langs);
        foreach ($langs as &$lang) {
            $lang = \Locale::getDisplayName($lang);
        }

        $builder->add('language', 'choice', array(
            'choices' => $langs,
            'required' => false,
        ));
    }

    public function getDefaultOptions(array $options)
    {
        return array(
            'languages' => array('fr_FR', 'en_GB'),
            'csrf_protection' => false,
        );
    }

    public function getName()
    {
        return 'my_language';
    }
}

I submit this form to a separate action in a controller, in which I set the locale and return a redirection to last page:

<?php
class LanguageController extends Controller
{
    public function switchLanguageAction()
    {
        $form = $this->get('form.factory')->create(
            new LanguageType(),
            array('language' => $this->get('session')->getLocale()),
            array('languages' => $this->container->getParameter('roger.admin.languages', null))
        );

        $request = $this->get('request');
        $form->bindRequest($request);
        $referer = $request->headers->get('referer');

        if ($form->isValid()) {
            $locale = $form->get('language')->getData();
            $router = $this->get('router');

            // Create URL path to pass it to matcher
            $urlParts = parse_url($referer);
            $basePath = $request->getBaseUrl();
            $path = str_replace($basePath, '', $urlParts['path']);

            // Match route and get it's arguments
            $route = $router->match($path);
            $routeAttrs = array_replace($route, array('_locale' => $locale));
            $routeName = $routeAttrs['_route'];
            unset($routeAttrs['_route']);

            // Set Locale
            $this->get('session')->setLocale($locale);

            return new RedirectResponse($router->generate($routeName, $routeAttrs));
        }

        return new RedirectResponse($referer);
    }
}

Works with any valid locale (you pass them as 'language' option while creating your form), provided that the PHP intl extension is enabled. If it's not, you'll need to replace \Locale::getDisplayName($lang) by a manually created list of locale names.

like image 22
wdev Avatar answered Oct 04 '22 20:10

wdev