diff --git a/examples/i18n.py b/examples/i18n.py new file mode 100644 index 00000000..6acafd51 --- /dev/null +++ b/examples/i18n.py @@ -0,0 +1,82 @@ +""" +Original docs link: https://docs.aiogram.dev/en/dev-3.x/utils/i18n.html +PROBLEM SOLUTION PROVIDED: +Aiogram handlers remember language on the start and there's no chance of changing it in handler's runtime. +So, here's a little hack in `change_language handler` + +# Cheatsheet to create/update locales: +## Generating new: +1. `pybabel extract -k __ --input-dirs=. -o locales/messages.pot` +2. `pybabel init -i locales/messages.pot -d locales -D messages -l ` +3. Open `locales/{language}/LC_MESSAGES/messages.po` and Translate msgs +4. `pybabel compile -d locales -D messages` + +## Updating: +1. `pybabel extract -k __ --input-dirs=. -o locales/messages.pot` +2. `pybabel update -d locales -D messages -i locales/messages.pot` +3. Open `locales/{language}/LC_MESSAGES/messages.po` and Translate msgs +4. `pybabel compile -d locales -D messages` + +""" +import asyncio +from typing import Any + +from aiogram import Bot, Dispatcher, Router +from aiogram import types +from aiogram.filters.command import Command, CommandStart +from aiogram.utils.i18n import gettext as _, I18n +from aiogram.utils.i18n.middleware import I18nMiddleware + + +class BotI18nMiddleware(I18nMiddleware): + async def get_locale(self, event: types.Update | Any, data: dict[str, Any]) -> str: + # here is your logic, ex. get language from redis DB + return 'en' + + +bot = Bot(token="") +router = Router() +dp = Dispatcher() +# NOTE: custom middleware is provided. You can use any middleware you want, ex: SimpleI18nMiddleware +i18n_middleware = BotI18nMiddleware( + I18n( + path="locales", + default_locale="en", + domain="messages" + ) +) +dp.update.outer_middleware(i18n_middleware) + + +@router.message(CommandStart()) +async def start_handler(message: types.Message): + await message.answer( + _("Hello!. Write /language . Ex: /language ru") + ) + + +@router.message(Command("language")) +async def change_language(message: types.Message): + """ + This function dynamically changes language inside of handler + Handler input: /language . Ex: /language ru + + Aiogram saves language context on start, so we should change language in runtime + """ + new_lang = message.text.split(maxsplit=1)[1] + # change in runtime + with i18n_middleware.i18n.context(), i18n_middleware.i18n.use_locale(new_lang): + # all messages in this context will be translated to new_lang + await message.answer(_('Language was changed to {lang}').format(lang=new_lang)) + + +dp.include_router(router) + + +async def main(): + print("Bot started") + await dp.start_polling(bot) + + +if __name__ == "__main__": + asyncio.run(main())