3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger
3 horizontal lines, burger

3 horizontal lines, burger
Remove all
LOADING ...

Content



    How to add translations(localisation) for your telegram bot in aiogram/python + i18n

    Clock
    14.01.2025
    /
    Clock
    11.03.2026
    /
    Clock
    4 minutes
    An eye
    3821
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0

    Introduction

    Our bot example will consist of 2 *.py files, main.py and config.py. The first will contain the entry point and the corresponding handlers, and the second will contain the settings for translations. The code for the example was taken from the Bot-example for connecting the Inline mode.

    Necessary code and setup

    As I promised, we do translations. Firstly, create a locales directory in the project folder. Then add the following imports to the main.py file:
    import asyncio import logging import sys import uuid from aiogram import F from aiogram.types import Message, InlineQuery, InlineQueryResultArticle, InputTextMessageContent, InlineQueryResultPhoto from aiogram.utils.i18n import gettext as _ from aiogram.filters import Command from config import bot_dispatcher, bot @bot_dispatcher.inline_query(F.query == "greeting") async def send_greetings(inline_query: InlineQuery): results = [] results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title="Обычное приветствие", input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text="Приветствую я вас сегодня." ) )) results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title="Жёсткое приветствие", input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text="Ну чё, как дела" ) )) results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title="Спокойное приветствие", input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text="Привет" ) )) await inline_query.answer(results) @bot_dispatcher.inline_query(F.query == "memes") async def send_user_images(inline_query: InlineQuery): results = [] results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://wisconsinskydivingcenter.com/wp-content/uploads/2024/05/you-dont-need-a-parachute-to-go-skydiving-meme.jpeg", thumbnail_url="https://wisconsinskydivingcenter.com/wp-content/uploads/2024/05/you-dont-need-a-parachute-to-go-skydiving-meme.jpeg" )) results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://jungleroots.com/wp-content/uploads/2022/11/1_OkVxoXBTygSKB8K-zbB7uQ-300x176.jpeg", thumbnail_url="https://jungleroots.com/wp-content/uploads/2022/11/1_OkVxoXBTygSKB8K-zbB7uQ-300x176.jpeg" )) results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://livestorm.imgix.net/1127/1651607695-obi-wan-alarm-work-meme.jpeg?h=auto&w=730&fm=jpeg&auto=format&q=90&dpr=1", thumbnail_url="https://livestorm.imgix.net/1127/1651607695-obi-wan-alarm-work-meme.jpeg?h=auto&w=730&fm=jpeg&auto=format&q=90&dpr=1" )) await inline_query.answer(results) @bot_dispatcher.message(Command('help')) async def help(message: Message): await message.answer("Этот бот является примером того, как можно реализовать inline функционал для него.") await message.answer("/startapp - запустить приложение") await message.answer("@joker_gut_bot memes - запросить мемы для показа") await message.answer("@joker_gut_bot greeting - запросить ответы по умолчанию") @bot_dispatcher.message(Command("startapp")) async def start_app(message: Message): await message.answer("Этот бот является примером того, как можно реализовать inline функционал для него.") async def main() -> None: await bot_dispatcher.start_polling(bot) if __name__ == "__main__": logging.basicConfig(level=logging.INFO, stream=sys.stdout) asyncio.run(main())
    In the config.py file, we will set up a directory for storing translations and middleware, respectively.
    from aiogram import Bot, Dispatcher from aiogram.utils.i18n import I18n, SimpleI18nMiddleware with open(".env", "r") as file: buffer = file.read() line_pos = buffer.find("BOT_TOKEN") TOKEN = buffer[buffer.find("=", line_pos) + 1:] bot = Bot(TOKEN) bot_dispatcher = Dispatcher(bot=bot) # Set up translation i18n = I18n(path="locales", domain="messages") i18n_handler = SimpleI18nMiddleware(i18n) i18n_handler.setup(bot_dispatcher)

    Marking strings for translation

    After we have connected the relevant modules and set up the environment, we need to mark which strings we are going to translate. In main.py I created an alias.
    ... from aiogram.utils.i18n import gettext as _ ...
    Each line will need to be wrapped around the alias of gettext. The end result will look something like this:
    import asyncio import logging import sys import uuid from aiogram import F from aiogram.types import Message, InlineQuery, InlineQueryResultArticle, InputTextMessageContent, InlineQueryResultPhoto from aiogram.filters import Command from aiogram.utils.i18n import gettext as _ from config import bot_dispatcher, bot @bot_dispatcher.inline_query(F.query == "greeting") async def send_greetings(inline_query: InlineQuery): results = [] results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title=_("Обычное приветствие"), input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text=_("Приветствую я вас сегодня.") ) )) results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title=_("Жёсткое приветствие"), input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text=_("Ну чё, как дела") ) )) results.append(InlineQueryResultArticle( id=str(uuid.uuid4()), title=_("Спокойное приветствие"), input_message_content=InputTextMessageContent( disable_web_page_preview=True, message_text=_("Привет") ) )) await inline_query.answer(results) @bot_dispatcher.inline_query(F.query == "memes") async def send_user_images(inline_query: InlineQuery): results = [] results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://wisconsinskydivingcenter.com/wp-content/uploads/2024/05/you-dont-need-a-parachute-to-go-skydiving-meme.jpeg", thumbnail_url="https://wisconsinskydivingcenter.com/wp-content/uploads/2024/05/you-dont-need-a-parachute-to-go-skydiving-meme.jpeg" )) results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://jungleroots.com/wp-content/uploads/2022/11/1_OkVxoXBTygSKB8K-zbB7uQ-300x176.jpeg", thumbnail_url="https://jungleroots.com/wp-content/uploads/2022/11/1_OkVxoXBTygSKB8K-zbB7uQ-300x176.jpeg" )) results.append(InlineQueryResultPhoto( id=str(uuid.uuid4()), photo_url="https://livestorm.imgix.net/1127/1651607695-obi-wan-alarm-work-meme.jpeg?h=auto&w=730&fm=jpeg&auto=format&q=90&dpr=1", thumbnail_url="https://livestorm.imgix.net/1127/1651607695-obi-wan-alarm-work-meme.jpeg?h=auto&w=730&fm=jpeg&auto=format&q=90&dpr=1" )) await inline_query.answer(results) @bot_dispatcher.message(Command('help')) async def help(message: Message): await message.answer(_("Этот бот является примером того, как можно реализовать inline функционал для него.")) await message.answer(_("/startapp - запустить приложение")) await message.answer(_("@joker_gut_bot memes - запросить мемы для показа")) await message.answer(_("@joker_gut_bot greeting - запросить ответы по умолчанию")) @bot_dispatcher.message(Command("startapp")) async def start_app(message: Message): await message.answer(_("Этот бот является примером того, как можно реализовать inline функционал для него.")) async def main() -> None: await bot_dispatcher.start_polling(bot) if __name__ == "__main__": logging.basicConfig(level=logging.INFO, stream=sys.stdout) asyncio.run(main())

    Extracting strings

    Finally, you can start extracting strings to the locales folder. All strings and their data will be saved in the messages.pot file.
    pybabel extract --input-dirs=. -o locales/messages.pot

    Initializing locales and translated languages

    You will need to make exactly as many locales as languages ​​​​you are going to use. In my case, there are 2, and they are made like this:
    pybabel init -i locales/messages.pot -d locales -D messages -l en; pybabel init -i locales/messages.pot -d locales -D messages -l ru;

    Translate

    The first is English, the second is Russian. In the first case, after generation, you will need to write a translation. You will need to find the messages.po file in locales\en\LC_MESSAGES and write translations. In the second case, this is the original language. No need to do translations.

    Compiling translations

    Now let's compile the translations
    pybabel compile -d locales -D messages

    Updating translations

    The translations are ready. But what if you wanted to make changes to the translations or added another text? In this case, you need to update the translations. And to do this, you will have to perform slightly different steps than when initializing in the first steps.
    It is important to remember that we initialize only once. Then, unless you want to lose all the translations, you will need to update them in a special way. First, extract the changes from all files with translation strings.
    pybabel extract --input-dirs=. -o locales/messages.pot
    Afterward, we update all locales
    pybabel update -d locales -D messages -i locales/messages.pot
    And finally compile the translations.
    pybabel compile -d locales -D messages
    That's it, the translations have been updated and will be shown depending on the user's Telegram client settings.

    Conclusion

    Translations for bots in Telegram are not so easy and can cause quite a headache for those who do it for the first time. The most difficult step, in my opinion, is finding and wrapping the lines you need for translation. Because not all lines can be wrapped, but if you follow the basic rules, everything should work out. ( ̄︶ ̄)↗ 


    Do not forget to share, like and leave a comment :)

    Comments

    (0)

    captcha
    Send
    LOADING ...
    It's empty now. Be the first (o゚v゚)ノ

    Other

    Similar articles


    How to get a telegram bot token and initial setup for telegram bot

    Clock
    14.01.2025
    /
    Clock
    11.03.2026
    An eye
    9159
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    In this article you will see how I get the telegram bot token (via bot father), where I store the token and how I set it up

    Full localization for a Django website

    Clock
    06.02.2025
    /
    Clock
    07.04.2026
    An eye
    4745
    Hearts
    0
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    I'll show you how to completely make localization a Django website, describe the full process: setting up, extracting, collecting, and compiling translations. Covering all three translation scenarios, including files such …

    Fast implementation of a RESTful API for a Django website

    Clock
    24.02.2025
    /
    Clock
    08.04.2026
    An eye
    1047
    Hearts
    1
    Connected dots
    0
    Connected dots
    0
    Connected dots
    0
    Implementing a REST API for a Django website in short, clear steps with minimal code required. Also included is a demonstration of backend interaction via the client side of the …

    Used termins


    Related questions