简体   繁体   English

使用KnpMenuBundle和Symfony3的菜单项的翻译参数

[英]Translation parameters for menu items using KnpMenuBundle and Symfony3

Introduction 介绍

In my personal project I am using: 在我的个人项目中,我正在使用:

  • XAMPP with PHP v7.1.6 XAMPP与PHP v7.1.6
  • Symfony v3.3.6 Symfony v3.3.6
  • KnpMnenuBundle dev-master / 2.2.x-dev [link 1] , [link 2] , [link 3] in order to manage Menus. KnpMnenuBundle dev-master / 2.2.x-dev [link 1][link 2][link 3]以便管理菜单。
  • Bootstrap v3.3.7 Bootstrap v3.3.7
  • Bootstrap and KnpMenuBundle integration [link 4] Bootstrap和KnpMenuBundle集成[链接4]

Setting up 配置

To setup i used documentation in [2], [3] and code samples [4]. 要进行设置,我使用了[2],[3]和代码示例[4]中的文档。 My menu is working, integration between Bootstrap and KnpMenuBundle also works. 我的菜单正常运行, BootstrapKnpMenuBundle之间的集成也有效。

At the moment 在这一刻

Menu bundle works fine, simple translating works and integration works too. 菜单包可以正常工作, 简单的翻译工作和集成工作也可以。

My ProfileMenu code sample: 我的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;
}

menu rendering is shown in following image 菜单渲染如下图所示

菜单渲染

Question

How can i pass translation parameters (namely %username% ) to menu (powered by KnpMenuBundle) and get it to render as intended? 如何将翻译参数(即%username% )传递给菜单(由KnpMenuBundle提供支持),并使其按预期方式呈现?

How can one supply arguments: 一个供应商如何提供参数:

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

in the MenuBuilder ? MenuBuilder

MY CODE 我的密码

The code block in question is 有问题的代码块是

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

namely label string label字符串

Translating strings with parameters ordinarily, one would supply arguments like so: 通常使用参数翻译字符串,将提供如下参数:

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

Yet, i can not seem to figure out how to pass them in case of using KnpMenuBundle and Bootstrap integration. 但是,在使用KnpMenuBundleBootstrap集成的情况下,我似乎无法弄清楚如何传递它们。

Conclusion 结论

Please advise. 请指教。

Thank you for your time and knowledge. 感谢您的时间和知识。

You could declare your MenuBuilder as a service like this 您可以将MenuBuilder声明为这样的服务

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

Update MenuBuilder 's constructor according to the dependencies on the above definition 根据以上定义的依赖关系更新MenuBuilder的构造函数

With this you have access to all the things you need to perform your traduction 有了这个,您就可以访问执行交易所需的所有东西

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

You should have your traduction and then map it to your profileMenu(...) function logic 您应该拥有自己的导论,然后将其映射到您的profileMenu(...)函数逻辑

I don't use sames version of symfony/knpMenu than you so maybe this code won't work directly but you just have to adapt to your needs 我没有使用与您相同的symfony / knpMenu版本,因此此代码可能无法直接运行,但您只需要适应您的需求

Ask for question if you want if it isn't clear 询问是否不清楚

I hope I have helped you, if yes please mark the post as resolved ! 希望我对您有所帮助,如果可以,请将该帖子标记为已解决! : ) :)

Simple answer to your question 简单回答您的问题

Simply translate the label passed to addChild : 只需翻译传递给addChild的标签:

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

$this->translator is a \\Symfony\\Component\\Translation\\TranslatorInterface that is injected into the service creating the menu. $this->translator是一个\\Symfony\\Component\\Translation\\TranslatorInterface ,注入到创建菜单的服务中。 I got it by passing "@translator" as an argument to the constructor in services.yml . 我通过将"@translator"作为参数传递给services.yml的构造函数来实现的。

Add multiple child menus 添加多个子菜单

For the sake of completeness, I'll also note that every child menu must have a different name. 为了完整起见,我还要注意每个子菜单必须使用不同的名称。 So, if you want to create multiple menus with different parameters, make sure you don't copy/paste the first line without also changing the menu name. 因此,如果要创建具有不同参数的多个菜单,请确保在不更改菜单名称的情况下不复制/粘贴第一行。

Or use something like this: 或使用像这样的东西:

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

Or, if all the child menus are generated in one file: 或者,如果所有子菜单都在一个文件中生成:

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

If you don't use different names, only the last menu is displayed. 如果您不使用其他名称,则仅显示最后一个菜单。

Avoid missing translation warnings 避免错过翻译警告

With the above solution, the symfony toolbar and the log both report warnings about missing messages. 通过上述解决方案,symfony工具栏和日志均会报告有关丢失消息的警告。 That's because the provided label can't be found in the translation domain (in messages.yml or whatever you use for your translations). 这是因为在翻译域中(在messages.yml或用于翻译的任何内容中)找不到提供的标签。

To avoid those false positive, add the following line after the addChild call: 为了避免这些误报,请在addChild调用之后添加以下行:

$menu->addChild('Logged in as', array('label' => $label)
     ->setExtra('translation_domain', false);

A specific option extras.translation_params is available but not documented: https://github.com/KnpLabs/KnpMenuBundle/blob/master/src/Resources/views/menu.html.twig#L7 特定选项extras.translation_params可用,但未记录在文档中: https : //github.com/KnpLabs/KnpMenuBundle/blob/master/src/Resources/views/menu.html.twig#L7

You can use it in the same way you used the translation_domain option: 您可以使用与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()]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM