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
filesContexts
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"