Подтвердить что ты не робот

Селектор языка Symfony2

Я хотел бы объединить простую форму HTML, позволяющую пользователю изменять язык веб-приложений Symfony2 (т.е. со страницы en/faq перейти к fr/faq). Как это сделать надлежащим образом?

Я нашел хороший способ сделать это с Symfony, но не с Symfony2: http://symfony.com/blog/play-with-the-user-language

4b9b3361

Ответ 1

Самый простой способ, который я нашел, - сделать это непосредственно в шаблоне ветки. По крайней мере, он работает с 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>

Ответ 2

Вам нужно позвонить $this->get('session')->setLocale($locale) (заменить "сеанс" на "запрос" для Symfony 2.1) внутри вашего контроллера.

Я создал форму, к которой передаю массив языков:

<?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';
    }
}

Я передаю эту форму отдельному действию в контроллере, в котором я установил локаль и вернул перенаправление на последнюю страницу:

<?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 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);
    }
}

Работает с любым допустимым языком (вы передаете их как "язык" при создании своей формы), при условии, что расширение внутреннего интерфейса PHP включено. Если это не так, вам нужно заменить \Locale::getDisplayName($lang) на список созданных вручную имен локалей.

Ответ 3

Я не делал этого с формой, а просто с небольшими изображениями флагов в верхней части экрана. Каждый флаг является ссылкой на текущую страницу, но с двухбуквенным кодом языка в URL-адресе заменяется языком соответствующего флага. Мой шаблон макета имеет следующий код:

{% 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 %}

Функция replaceLanguageInUrl определена в моем классе расширения Twig:

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);
}

При щелчке по флагам загружается одна и та же страница, но на новом языке. Это также автоматически установит новый язык в сеансе.

Ответ 5

Я сделал это с локальным, но чем-то более простым, чем решение wdev, я использовал несколько изображений (флаги) в качестве кнопок. При щелчке по флагам новый языковой стандарт устанавливается, и страница обновляется (с перенаправлением) с новым языком. Вам нужно использовать систему перевода Symfony. Вот код:

Контроллер:

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'));
}

Шаблон:

<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>

Изменить: это решение работает с Symfony2.0, для Symfony2.1, проверьте этот вопрос