Я хотел бы объединить простую форму HTML, позволяющую пользователю изменять язык веб-приложения Symfony2 (т. Е. От страницы en / faq перейти к fr / faq). Как это сделать правильно?
Я нашел хороший способ сделать это с Symfony, но не с Symfony2: http://symfony.com/blog/play-with-the-user-language
Самый простой способ, который я нашел, – сделать это непосредственно в шаблоне ветки. По крайней мере, он работает с 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>
Вам нужно вызвать $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'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); } }
не<?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); } }
Работает с любым допустимым языком (вы передаете их как «язык» при создании своей формы), при условии, что расширение внутреннего интерфейса PHP включено. Если это не так, вам нужно будет заменить \Locale::getDisplayName($lang)
вручную созданным списком имен \Locale::getDisplayName($lang)
.
Я не делал этого с формой, но просто с небольшими изображениями флагов в верхней части экрана. Каждый флаг является ссылкой на текущую страницу, но с двухбуквенным кодом языка в 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); }
При щелчке по флагам загружается одна и та же страница, но на новом языке. Это также автоматически установит новый язык в сеансе.
Использование параметра _locale
в определении маршрутизации автоматически устанавливает локаль пользователя.
См. http://symfony.com/doc/current/book/translation.html#the-locale-and-the-url
Я сделал это с локальным, но чем-то более простым, чем решение 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 проверить этот вопрос