How to display a literal ampersand ('&') in Action name?

Hello,

I’m struggling with a seemingly simple task: I want to display a single ampersand character (&) in my action’s text.

What I’ve tried:

  • text="Project & Non-Project Modules" → Result: The “N” is underlined as a mnemonic.
  • text="Project && Non-Project Modules" → Result: No mnemonic and no (&).
  • text="Project && Non-Project Modules" → Result: Same as above.

I have defined my action in plugin.xml as follows:

<action id="pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules"
        class="pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules"
        text="Project &amp;&amp; Non-Project Modules">
    <keyboard-shortcut
            keymap="$default"
            first-keystroke="alt B"
            second-keystroke="N"/>
</action>

You need to say &&, see

Example in properties file:

Thank you for your reply.

When I use && in plugin.xml:

<action id="pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules"
        class="pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules"
        text="Project && Non-Project Modules">
    <keyboard-shortcut
            keymap="$default"
            first-keystroke="alt B"
            second-keystroke="N"/>
</action>

Then I get:

The entity name must immediately follow the '&' in the entity reference.

And when I use it in bundle.properties:

action.pl.atingo.bts.actions.OdooModuleTestWithRemoveDB.description=Project && Non-Project Modules

Then I get:

com.intellij.diagnostic.PluginException: Empty menu item text for OdooModuleTestProjectNonProjectModules@popup (pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules). The default action text must be specified in plugin.xml or its class constructor [Plugin: pl.atingo.bts]

Looks like you have a typo in the properties file example

your ID is pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules but you registered it with the ID pl.atingo.bts.actions.OdooModuleTestWithRemoveDB

My apologies, I completely messed up the examples in my previous post. I’ve been testing so many different configurations that I got lost in my own snippets. Let’s clear this up:

  • The plugin.xml issue: When I try to use && directly in the text attribute like this: text="Project && Non-Project Modules" I get the expected XML error: The entity name must immediately follow the '&' in the entity reference. This is clear, as XML requires entities.
  • The bundle.properties issue (with the correct ID this time): When I use the correct action ID in my properties file: action.pl.atingo.bts.actions.OdooModuleTestProjectNonProjectModules.text=Project && Non-Project Modules, the action loads correctly, but the & character is simply not displayed.

Interesting, wonder if its a bug…?

It works with && only if its done through the AnAction constructor

AnAction("Foo && Bar") {

Screenshot 2026-04-14 at 9.50.07 AM

I got curious so I debugged this:

When using ActionStub (defining it in the properties file), the text is loaded via

Which has to go through Java’s Message format and this util:

So in order to get it formatted correct from the resource bundle PoV it would need to be:
action.foo.bar.text=Foo \\& Bar

But the format is then passed to Presentation.setText supplier, which wants it in && format.

So we have to triple escape this for all the layers:

& -> && for com.intellij.openapi.util.text.TextWithMnemonic#parse
&& -> \&\& for com.intellij.BundleBase#replaceMnemonicAmpersand
\&\& -> \\&\\& for Java MessageFormat

leading us to

action.foo.bar.text=Foo \\&\\& Bar

That’s it! \\&\\& did the trick

Thank you so much for digging into the code and debugging this.

Cheers!