IslamBot icon indicating copy to clipboard operation
IslamBot copied to clipboard

Localization

Open galacticwarrior9 opened this issue 2 years ago • 5 comments

The bot is used on several servers where the primary language is neither English or Arabic.

The usage of user-contributed translations will increase the accessibility of the bot to more communities.

galacticwarrior9 avatar Apr 24 '22 00:04 galacticwarrior9

Add a command to set language of a server? And, how exactly will this be coded? Is there any other way than repeating the same string for multiple languages, then doing a check for the language of the server?

itzmk21 avatar Apr 24 '22 00:04 itzmk21

look to help need some knowledge about this issue

MuhammadSaadSiddique avatar Oct 20 '22 05:10 MuhammadSaadSiddique

Discord.py supports localizing slash commands based on a user's selected language. It works for command names, command descriptions, parameter names, parameter descriptions, and choice names.

Documentation: https://discordpy.readthedocs.io/en/latest/interactions/api.html?highlight=translation#discord.app_commands.Translator

Small example that prepends “gb” to all texts for en-GB users:

# translation.py
from typing import Optional
import discord

class MyCustomTranslator(discord.app_commands.Translator):
    async def translate(self, string: discord.app_commands.locale_str, locale: discord.Locale, context: discord.app_commands.TranslationContext) -> Optional[str]:
        message_str = string.message
        locale_str = str(locale)

        if locale_str == 'en-GB':
            return 'gb' + message_str
        else:
            return None

and then in the setup_hook there would be an extra line await bot.tree.set_translator(MyCustomTranslator()).

msabur avatar Jul 19 '23 23:07 msabur

So, there's this:

class MyCustomTranslator(app_commands.Translator):
  async def load(self):
    # this gets called when the translator first gets loaded!
  async def unload(self):
    # in case you need to switch translators, this gets called when being removed
  async def translate(self, string: app_commands.locale_str, locale: discord.Locale, context: app_commands.TranslationContext) -> Optional[str]:
    """
    `locale_str` is the string that is requesting to be translated
    `locale` is the target language to translate to
    `context` is the origin of this string, eg TranslationContext.command_name, etc
    This function must return a string (that's been translated), or `None` to signal no available translation available, and will default to the original.
    """
    message_str = string.message
    return your_translate(message_str)
# IMPORTANT! put this in your `setup_hook` function
await bot.tree.set_translator(MyCustomTranslator())
# Optional, but helps save a lot of typing
from discord.app_commands import locale_str as _T
@app_commands.command(name=_T("bonk"))
@app_commands.describe(user=_T("The user to bonk."))
async def bonk(interaction: discord.Interaction, user: discord.User):
  await interaction.response.send_message(f":hammer: {user.mention}")

The digging around I've done suggest we need a format of how translations will be stored, right? One possible solution is using the gettext module in Python, then storing translations in different files, or maybe simply a JSON file, I really don't know lol.

itzmk21 avatar Jul 20 '23 01:07 itzmk21

I think using gettext would be better. Using JSON would give the greatest flexibility. However, with gettext there are CLI tools to help with management tasks like updating translations when the strings change. There are also GUI/CLI tools for working with translation files, which could help contributors. Downsides of gettext are that there’s an extra step of compiling the translation files, and that the CLI tools can have a slight learning curve.

msabur avatar Aug 05 '23 00:08 msabur