Вступление Наш бот пример будет состоять из 2х
*.py файлов,
main.py и
config.py .
В первом будет точка входа и соответствующие обработчики, а
во втором настройка для переводов. Код для примера был взят из
Бота-примера для подключения Inline режима .
Необходимый код и настройка Как я и обещал делаем переводы. В первую очередь, создай директорию locales в папке проекта. После добавь следующие импорты в файл main.py :
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
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())
В файле config.py мы настроим директорию для хранения переводов и мидлвари переводов соответственно .
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
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)
i18n = I18n(path="locales" , domain="messages" )
i18n_handler = SimpleI18nMiddleware(i18n)
i18n_handler.setup(bot_dispatcher)
Помечаем строчки для перевода После того как мы подключили соответствующие модули и настроили среду, необходимо пометить какие строчки мы собираемся перевести. В main.py я создал алиас нижнее подчёркивание .
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
...
from aiogram.utils.i18n import gettext as _
...
Каждую строку необходимо будет обернуть вокруг алиаса нижнее_подчёркивание. По итогу получиться что-то вроде этого:
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
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())
Извлекаем строчки Наконец можно начать извлечения строк в папку locale. Все строки и данные о них будут сохранены в messages.pot файле.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel extract --input-dirs=. -o locales/messages.pot
Инициализируем локали и переводимые языки Ты должен будешь сделать ровно столько локалей, сколько языков ты собираешься использовать. В моём случае их 2, и делаются они вот так:
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel init -i locales/messages.pot -d locales -D messages -l en;
pybabel init -i locales/messages.pot -d locales -D messages -l ru;
Переводим Первая английская, вторая русская. В первом случае, после генерации необходимо будет написать перевод. Ты должен будешь найти файл messages.po в locales\en\LC_MESSAGES и написать переводы. Во втором случае, это язык оригинала, переводы делать не надо.
Компиляция переводов Теперь скомпилируем переводы
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel compile -d locales -D messages
Обновляем переводы Переводы готовы. Но что если ты захотел внести изменения в переводы или добавил другой текст? В таком случае нужно обновить переводы. И для этого придётся выполнить немного другие шаги, нежели чем при инициализации в первых шагах.
Важно помнить, что мы инициализируем только раз. Дальше, если ты конечно не хочешь потерять все переводы, нужно будет их обновлять специальным способом. Сначала извлекаем из всех файлов с переводами изменения в них.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel extract --input-dirs=. -o locales/messages.pot
После обновляем все локали
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel update -d locales -D messages -i locales/messages.pot
И наконец компилируем переводы.
Plain Bash C++ C# CSS Diff HTML/XML Java JavaScript Markdown PHP Python Ruby SQL
pybabel compile -d locales -D messages
Всё, переводы обновлены и будут показываться в зависимости от настроек телеграм-клиента у пользователя.
Заключение Переводы для ботов в телеграм не так просто и могут вызвать достаточно головной боли для того, кто делает это в первые. Самый сложный шаг, на мой взгляд это поиск и оборачивание необходимых тебе строк для перевода. Ибо не все строчки можно обернуть, но если следовать базовым правилам всё должно получиться. ( ̄︶ ̄)↗