Symfony2 language selector

前端 未结 5 606
深忆病人
深忆病人 2020-12-24 09:18

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

相关标签:
5条回答
  • I did it with the local too but something more simple than wdev's solution, i used some pictures (flags) as buttons. When the flag is clicked, the new locale is set and the page is refreshed (with a redirect) with the new language. You need to use Symfony's translation system. Here is the code:

    Controller:

    public function englishAction(Request $request)
    {
        $this->get('session')->setLocale('en_US');
        return $this->redirect($request->headers->get('referer'));
    }
    
    public function chineseAction(Request $request)
    {
        $this->get('session')->setLocale('zh_CN');
        return $this->redirect($request->headers->get('referer'));
    }
    
    public function frenchAction(Request $request)
    {
        $this->get('session')->setLocale('fr_FR');
        return $this->redirect($request->headers->get('referer'));
    }
    

    Template:

    <ul class="nav pull-right">
         <li>
               <a href="{{ path('english') }}"><img src="{{ asset('bundles/fkmywebsite/images/flag-en.png') }}" alt="English Language" height="30" width="18" /></a>
         </li>
         <li>
              <a href="{{ path('chinese') }}"><img src="{{ asset('bundles/fkmywebsite/images/flag-cn.jpg') }}" alt="Chinese Language" height="30" width="18" /></a>
        </li>
        <li>
            <a href="{{ path('french') }}"><img src="{{ asset('bundles/fkmywebsite/images/flag-fr.png') }}" alt="French Language" height="30" width="18" /></a>
        </li>
    </ul>
    

    Edit: This solution works with Symfony2.0, for Symfony2.1 check this question

    0 讨论(0)
  • 2020-12-24 09:35

    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>
    
    0 讨论(0)
  • 2020-12-24 09:45

    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.

    0 讨论(0)
  • 2020-12-24 09:48

    I have not done this with a form, but simply with small flag images at the top of the screen. Each flag is a link to the current page, but with the two-letter language code in the URL replaced by the language of the respective flag. My layout template has the following code:

    {% for language, description in languages %}
        <a href="{{ replaceLanguageInUrl(app.session.locale, language, app.request.uri) }}">
        <img src="{{ asset('images/flag_' ~ language ~ '.png') }}" alt="" title="{{ description }}"/>
        </a>
    {% endfor %}
    

    The replaceLanguageInUrl function is defined in my Twig extension class:

    public function getFunctions()
    {
        return array(
            'replaceLanguageInUrl' => new \Twig_Function_Method($this, 'replaceLanguageInUrl'),
        );
    }    
    
    public function replaceLanguageInUrl($currentLanguage, $newLanguage, $url)
    {
    
        //EDIT BEGIN
        if (strpos($url,$currentLanguage) == false) {
            $url = getBaseUrl($url).'/'.$currentLanguage;
        }
        //EDIT END
        return str_replace('/' . $currentLanguage . '/', '/' . $newLanguage . '/', $url);
    }
    

    When a flag is clicked, the same page is loaded, but in the new language. This will also automatically set the new language in the session.

    0 讨论(0)
  • 2020-12-24 09:54

    Using the _locale parameter in your routing definition automatically sets the user locale.

    See http://symfony.com/doc/current/book/translation.html#the-locale-and-the-url

    0 讨论(0)
提交回复
热议问题