Параметры перевода пунктов меню с использованием KnpMenuBundle и Symfony3

Введение

В моем личном проекте я использую:

Настройка

Для настройки я использовал документацию в [2], [3] и примеры кода [4]. Меню у меня работает, интеграция между Bootstrap и KnpMenuBundle тоже работает.

В данный момент

Пакет меню работает нормально, работает простой перевод и интеграция.

Мой пример кода ProfileMenu:

public function profileMenu(array $options)
{
    $menu = $this->factory->createItem('root');
    $menu->setChildrenAttribute('class', 'nav navbar-nav navbar-right');

    $menu->addChild('Profile', array('label' => 'menu.profile'))
        ->setExtras(array('dropdown' => true, 'icon' => 'fa fa-user'))
        ->setLinkAttribute('class', "dropdown-toggle")
        ->setLinkAttribute('data-toggle', "dropdown")
        ->setExtra('translation_domain', 'menu');

    $menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
        ->addChild('Logged in as', array('label' => 'layout.logged_in_as'))
        ->setExtra('divider_append', true)
        ->setExtra('translation_domain', 'FOSUserBundle');

    $menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
        ->addChild('My data', array('label' => 'menu.profile.myData', 'route' => 'fos_user_profile_show'))
        ->setExtra('translation_domain', 'menu');
    $menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
        ->addChild('Edit data', array('label' => 'menu.profile.editMyData', 'route' => 'fos_user_profile_edit'))
        ->setExtra('translation_domain', 'menu');
    $menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
        ->addChild('Change password', array('label' => 'menu.profile.changePassword', 'route' => 'fos_user_change_password'))
        ->setExtra('translation_domain', 'menu');

    $menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
        ->addChild('Exit', array('label' => 'menu.profile.logout', 'route' => 'fos_user_security_logout'))
        ->setExtra('divider_prepend', true)
        ->setExtra('translation_domain', 'menu');

    return $menu;
}

рендеринг меню показан на следующем изображении

рендеринг меню

Вопрос

Как я могу передать параметры перевода (а именно %username%) в меню (работает на KnpMenuBundle) и заставить его отображаться так, как задумано?

Как можно привести аргументы:

|trans({'%username%': app.user.username}

в MenuBuilder?

МОЙ КОД

Рассматриваемый блок кода

$menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
    ->addChild('Logged in as', array('label' => 'layout.logged_in_as'))
    ->setExtra('divider_append', true)
    ->setExtra('translation_domain', 'FOSUserBundle');

а именно label строка

При обычном переводе строк с параметрами можно было бы указать такие аргументы:

<li><a href="#">{{ 'layout.logged_in_as'|trans({'%username%': app.user.username}, 'FOSUserBundle') }}</a></li>

Тем не менее, я не могу понять, как их передать в случае использования интеграции KnpMenuBundle и Bootstrap.

Вывод

Пожалуйста, порекомендуйте.

Спасибо за ваше время и знания.


person Rikijs    schedule 22.08.2017    source источник
comment
У меня есть дополнительный вопрос stackoverflow.com/q/46007289/3137047   -  person Rikijs    schedule 01.09.2017


Ответы (3)


Вы можете объявить свой MenuBuilder как услугу, подобную этой

#services.yml
app.menu_builder:
        class: AppBundle\Menu\MenuBuilder
        arguments:
            - @knp_menu.factory
            - @security.token_storage
            - @translator.default

Обновите конструктор MenuBuilder в соответствии с зависимостями от приведенного выше определения.

Благодаря этому у вас есть доступ ко всему, что вам нужно для выполнения перевода.

$user = $this->tokenStorage->getToken()->getUser(); // If you are under a path protect by security.yml access_constrol
$yourLoggedInTraduction = $this->translator->trans(
    'layout.logged_in_as', [
        '%username%' => $user->getUsername()
    ], 
    'FOSUserBundle', 
    'yourlocale'
); 
dump($yourLoggedInTraduction);

Вы должны иметь свой перевод, а затем сопоставить его с логикой вашей profileMenu(...) функции.

Я не использую ту же версию symfony/knpMenu, что и вы, поэтому, возможно, этот код не будет работать напрямую, но вам просто нужно адаптироваться к вашим потребностям

Задайте вопрос, если хотите, если это неясно

Надеюсь, я помог вам, если да, пожалуйста, отметьте сообщение как решенное! :)

person Mcsky    schedule 22.08.2017

Конкретная опция extras.translation_params доступна, но не задокументирована: https://github.com/KnpLabs/KnpMenuBundle/blob/master/src/Resources/views/menu.html.twig#L7

Вы можете использовать его так же, как вы использовали опцию translation_domain:

$menu['Profile']->setChildrenAttribute("class", "dropdown-menu")
    ->addChild('Logged in as', array('label' => 'layout.logged_in_as'))
    ->setExtra('divider_append', true)
    ->setExtra('translation_domain', 'FOSUserBundle')
    ->setExtra('translation_params', ['%username%' => $user->getUsername()]);
person Seb33300    schedule 20.03.2019

Простой ответ на ваш вопрос

Просто переведите метку, переданную addChild:

$label = $this->translator->trans('layout.logged_in_as', ['%user%' => $username ]);
$menu->addChild('Logged in as', array('label' => $label);

$this->translator — это \Symfony\Component\Translation\TranslatorInterface, который внедряется в службу, создающую меню. Я получил его, передав "@translator" в качестве аргумента конструктору в services.yml.

Добавить несколько дочерних меню

Для полноты отмечу также, что каждое дочернее меню должно иметь другое имя. Итак, если вы хотите создать несколько меню с разными параметрами, убедитесь, что вы не копируете/вставляете первую строку без изменения имени меню.

Или используйте что-то вроде этого:

$idx = 0;
$menu->addChild("Language_".$idx++, array('label' => $label_lang1);
$menu->addChild("Language_".$idx++, array('label' => $label_lang2);

Или, если все дочерние меню генерируются в одном файле:

$menu->addChild("Language_".__LINE__, array('label' => $label_lang1);
$menu->addChild("Language_".__LINE__, array('label' => $label_lang2);

Если вы не используете другие имена, отображается только последнее меню.

Избегайте предупреждений об отсутствии перевода

В приведенном выше решении панель инструментов symfony и журнал сообщают о предупреждениях об отсутствующих сообщениях. Это связано с тем, что предоставленную метку нельзя найти в домене перевода (в messages.yml или в том, что вы используете для своих переводов).

Чтобы избежать этих ложных срабатываний, добавьте следующую строку после вызова addChild:

$menu->addChild('Logged in as', array('label' => $label)
     ->setExtra('translation_domain', false);
person Frédéric Marchal    schedule 13.02.2018