Localization

Application commands can be localized, which will cause them to use localized names and descriptions depending on the client’s selected language. Localization is available for names and descriptions of commands, subcommands, and options, as well as the names of choices.

Not all available locales are required, nor do different fields within a command need to support the same set of locales. If a locale is not present in a localizations dictionary for a field, users in that locale will see the default value for that field. It’s not necessary to fill out all locales with the default value. Any localized values that are identical to the default will be ignored.

See also

Discord documentation


Implementation

To implement localization within your bot, you must first supply a localization provider when creating the Client. This provider will be used to resolve all localizations for the previously mentioned fields. This resolution step only occurs when the bot is started due to them being needed while syncing commands with Discord.

A localization provider is any callable (synchronous or asynchronous) that when called with a localization key, returns the dictionary mapping locales to the localized strings for that key.

Lightbulb provides two localization providers by default. The more basic one DictLocalizationProvider simply provides localizations from the dict it is given upon instantiation. The other included provider - GnuLocalizationProvider - provides localizations from a gettext-compatible file path using .po or .mo files.

Once you have set up a localization provider, you can simply pass localize=True to any items that you wish to localize and Lightbulb will resolve the correct localizations from the name (and description) keys.


Setting Default Locale

The default locale defines what localizations the client will use as the default when creating commands. You can change this by passing a different locale to the default_locale kwarg when creating the client. This defaults to EN_US.


DictLocalizationProvider

Usage of this provider is extremely simple. A complete example is shown below.

import hikari
import lightbulb

bot = hikari.GatewayBot(...)

localization_provider = lightbulb.DictLocalizationProvider({
    hikari.Locale.EN_US: {
        "commands.echo.name": "echo",
        "commands.echo.description": "repeats the given text",
        "commands.echo.options.text.name": "text",
        "commands.echo.options.text.description": "text to repeat"
    },
    hikari.Locale.ES_ES: {
        "commands.echo.name": "eco",
        "commands.echo.description": "repite el texto dado",
        "commands.echo.options.text.name": "texto",
        "commands.echo.options.text.description": "texto a repetir"
    }
})
client = lightbulb.client_from_app(bot, localization_provider=localization_provider)
bot.subscribe(hikari.StartingEvent, client.start)


@client.register
class Echo(
    lightbulb.SlashCommand,
    # The below values are used as the keys from which to resolve the correct localizations from
    name="commands.echo.name",
    description="commands.echo.description",
    # This command should be localized
    localize=True,
):
    text = lightbulb.string(
        "commands.echo.options.text.name",
        "commands.echo.options.text.description",
        localize=True,
    )

    @lightbulb.invoke
    async def invoke(self, ctx: lightbulb.Context) -> None:
        await ctx.respond(self.text)


bot.run()

GnuLocalizationProvider

This provider is more complex and relies on the correct file structure being present in order to work correctly. With the default values, your project structure could look something like this.

bot.py
translations/
├── en-US/
│   └── LC_MESSAGES/
│       └── commands.po
└── es-ES/
    └── LC_MESSAGES/
        └── commands.po

The expected path can be modified by passing different values to the directory, category, and filename arguments when instantiating the provider.

Warning

This provider does not support the following features:

  • Plurals

  • .pot files

  • Contexts

You should use only the most barebone .po files possible. If you need more features for other functionality you should use a differently named file.

Implementing the previous example again but using this localization provider instead would look like this. Note that in this example we are using the same project structure mentioned before.

import hikari
import lightbulb

bot = hikari.GatewayBot(...)
client = lightbulb.client_from_app(bot, localization_provider=lightbulb.GnuLocalizationProvider("commands.po"))
bot.subscribe(hikari.StartingEvent, client.start)


@client.register
class Echo(
    lightbulb.SlashCommand,
    # The below values are used as the keys from which to resolve the correct localizations from
    name="commands.echo.name",
    description="commands.echo.description",
    # This command should be localized
    localize=True,
):
    text = lightbulb.string(
        "commands.echo.options.text.name",
        "commands.echo.options.text.description",
        localize=True,
    )

    @lightbulb.invoke
    async def invoke(self, ctx: lightbulb.Context) -> None:
        await ctx.respond(self.text)


bot.run()
msgid ""
msgstr ""
"Project-Id-Version: Lightbulb Demo\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-02 15:25+0000\n"
"PO-Revision-Date: 2024-07-02 15:25+0000\n"
"Last-Translator: \n"
"Language-Team: English\n"
"Language: en-US\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "commands.echo.name"
msgstr "echo"

msgid "commands.echo.description"
msgstr "repeats the given text"

msgid "commands.echo.options.text.name"
msgstr "text"

msgid "commands.echo.options.text.description"
msgstr "text to repeat"
msgid ""
msgstr ""
"Project-Id-Version: Lightbulb Demo\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-02 15:25+0000\n"
"PO-Revision-Date: 2024-07-02 15:25+0000\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Language: es-ES\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

msgid "commands.echo.name"
msgstr "eco"

msgid "commands.echo.description"
msgstr "repite el texto dado"

msgid "commands.echo.options.text.name"
msgstr "texto"

msgid "commands.echo.options.text.description"
msgstr "texto a repetir"