Как добавить переводы для твоего телеграм бота

Часы
14.01.2025
Глазик
51
Сердечки
0
Соединённые точки
0
Соединённые точки
0
Соединённые точки
0

Вступление

Наш бот пример будет состоять из 2х *.py файлов, main.py и config.py. В первом будет точка входа и соответствующие обработчики, а во втором настройка для переводов. Код для примера был взят из Бота-примера для подключения Inline режима.

Необходимый код и настройка

Как я и обещал делаем переводы. В первую очередь, создай директорию locales в папке проекта. После добавь следующие импорты в файл main.py:
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 мы настроим директорию для хранения переводов и мидлвари переводов соответственно.
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)

Помечаем строчки для перевода

После того как мы подключили соответствующие модули и настроили среду, необходимо пометить какие строчки мы собираемся перевести. В main.py я создал алиас нижнее подчёркивание.
...
from aiogram.utils.i18n import gettext as _
...
Каждую строку необходимо будет обернуть вокруг алиаса нижнее_подчёркивание. По итогу получиться что-то вроде этого:
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 файле.
pybabel extract --input-dirs=. -o locales/messages.pot

Инициализируем локали и переводимые языки

Ты должен будешь сделать ровно столько локалей, сколько языков ты собираешься использовать. В моём случае их 2, и делаются они вот так:
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 и написать переводы. Во втором случае, это язык оригинала, переводы делать не надо.

Компиляция переводов

Теперь скомпилируем переводы
pybabel compile -d locales -D messages

Обновляем переводы

Переводы готовы. Но что если ты захотел внести изменения в переводы или добавил другой текст? В таком случае нужно обновить переводы. И для этого придётся выполнить немного другие шаги, нежели чем при инициализации в первых шагах.
Важно помнить, что мы инициализируем только раз. Дальше, если ты конечно не хочешь потерять все переводы, нужно будет их обновлять специальным способом. Сначала извлекаем из всех файлов с переводами изменения в них.
pybabel extract --input-dirs=. -o locales/messages.pot
После обновляем все локали
pybabel update -d locales -D messages -i locales/messages.pot
И наконец компилируем переводы.
pybabel compile -d locales -D messages
Всё, переводы обновлены и будут показываться в зависимости от настроек телеграм-клиента у пользователя.

Заключение

Переводы для ботов в телеграм не так просто и могут вызвать достаточно головной боли для того, кто делает это в первые. Самый сложный шаг, на мой взгляд это поиск и оборачивание необходимых тебе строк для перевода. Ибо не все строчки можно обернуть, но если следовать базовым правилам всё должно получиться. ( ̄︶ ̄)↗ 


Комментарии

(0)
captcha
Отправить
Сейчас тут пусто. Буть первым (o゚v゚)ノ