Package: cb-i18n
cb-i18nAdvanced internationalisation (i18n) support for Discord botsThis module works with any well-known Discord API library for Python, including:discord.py(and any derived libraries such asdisnake,nextcordandpycord)hikari.pyInstallationInstall with pip:# Linux / MacOSpython3-mpipinstallcb-i18n# Windowspy-3-mpipinstallcb-i18nInstall from source:gitclonehttps://github.com/LTT/cb-i18ncdcb-i18n
python3setup.pyinstall# Windowsgitclonehttps://github.com/LTT/cb-i18ncdcb-i18n
py-3setup.pyinstallExample usage ofcb-i18n:In fact, this library can work with just any application written in python. The first arg inTranslator.translatecan beanything, you can pass integer, string, custom object or even module, all will work as expected by you. Internally, lib does nothing with that "context", it just passing it to yourlocale_getterand all.Directory structure:src/
  languages/
    en-US.json
    ru-RU.json
  main.pysrc/languages/en-US.json:{"Hello {}":"Hello {}",// Positional placeholders"You're a Genius!":"You're a Genius!",// No placeholders"Locale is now {locale}":"Locale is now {locale}"// Keyword-only placeholders}src/languages/ru-RU.json:{"Hello {}":"РџСЂРёРІРµС‚ {}","You're a Genius!":"Р”Р° С‚С‹ РіРµРЅРёР№!","Locale is now {locale}":"РЇР·С‹Рє С‚РµРїРµСЂСЊ {locale}"}src/main.py:importsqlite3importdisnakefromdisnake.extimportcommandsimportcb_i18nasi18nbot=commands.Bot("!",intents=disnake.Intents.all())connection=sqlite3.connect('mydatabase.db')cursor=connection.cursor()translator=None_=Nonedefget_locale(ctx:commands.Context):returncursor.execute("SELECT locale FROM guilds WHERE id = ?;",ctx.guild.id).fetchone()[0]@bot.eventasyncdefon_ready():print("Bot loading")cursor.execute("CREATE TABLE IF NOT EXISTS guilds (id bigint, locale text);")connection.commit()print("  Loading guilds table...")forguildinbot.guilds:ifnotcursor.execute("SELECT * FROM guilds WHERE id = ?",guild.id).fetchone():print("    Guild{}: not exist".format(guild.id))cursor.execute("INSERT INTO guilds VALUES (?, ?);",guild.id,"en-US")connection.commit()else:print("    Guild{}: exists".format(guild.id))print("  Loaded guilds table.")print("  Loading i18n...")globaltranslator,_translator=i18n.make_translator()translator.set_locale_dir("./languages/")translator.set_locale_getter(get_locale)translator.load_translations()_=translator.translateprint("  Loaded i18n.")print("Bot ready!\nAccount:{}(ID:{})\nGuild count:{}\nUser count:{}".format(str(bot.user),bot.user.id,len(bot.guilds),len(bot.users)))@bot.command(description="Set locale for a guild",aliases=["setlocale","set-locale"])asyncdefset_locale(ctx:commands.Context,locale:str):cursor.execute("UPDATE guilds SET locale = ? WHERE id = ?;",locale,ctx.guild.id)connection.commit()returnawaitctx.send(_(ctx,"Locale is now{locale}").format(locale=locale))@bot.command(description="Say hi!")asyncdefhi(ctx:commands.Context,name:str):returnawaitctx.send(_(ctx,"Hello{}").format(name))@bot.command(description="You're Genius, right?")asyncdefgenius(ctx:commands.Context):returnawaitctx.send(_(ctx,"You're a Genius!"))try:bot.run(os.environ.get("BOT_TOKEN"))exceptExceptionasexc:print(exc.__class__.__name__+": "+exc.__str__()+"".join(tb.format_exception(exc)))finally:cursor.close()connection.close()