Переклад

Для того, чтобы Ваш бот володив декилькома мовами, необходимо добавить минимальну килькисть хукив к вашого Python коду

Ци хуки звуться рядками передкладу

Утилити перевода побудовани на основе модулю GNU gettext Python и Babel library.

Всиновлення

Babel потрибний для забезпечення простоти експорту рядкив перевода с Вашого коду.

Можна всиновити непосредственно с pip:

pip install Babel

или как кдаткову зависимость litegram:

pip install litegram[i18n]

Как зробити сообщение переводимыми?

Для того, чтобы gettext знав которые строки следует перекласти, Вам необходимо видмитити строки перевода.

Например:

from litegram import html
from litegram.utils.i18n import gettext as _

async def my_handler(message: Message) -> None:
    await message.answer(
        _("Hello, {name}!").format(
            name=html.quote(message.from_user.full_name)
        )
    )

Опасно

f-строки не можно использовать как строки перевода, поскольку будь-которые динамические переменные следует добавить к сообщения после получения переведенного сообщения

Крим того, если Ви бажаете використати перекладений строку в фильтрах, Вам треба використати видкладений перевод (lazy gettext):

from litegram import F
from litegram.utils.i18n import lazy_gettext as __

@router.message(F.text == __("My menu entry"))
...

Опасно

Отложенные вызовы gettext следует всегда использовать, когда поточна мова на даний момент невидома.

Опасно

Отложенные вызовы gettext не можно использовать как значение для методив API или будь-которого объекта Telegram (например, litegram.types.inline_keyboard_button.InlineKeyboardButton и т.д.)

Working with plural forms

The gettext from litegram.utils.i18n is the one alias for two functions _gettext_ and _ngettext_ of GNU gettext Python module. Therefore, the wrapper for message strings is the same _(). You need to pass three parameters to the function: a singular string, a plural string, and a value.

from litegram import html
from litegram.utils.i18n import gettext as _

async def my_handler(message: Message) -> None:
    try:
        n = int(message.text)
    except ValueError:
        n = 1
    await message.answer(
        _("You ordered {n} piece.", "You ordered {n} pieces.",n).format(n)
        )
    )

Налаштування рушия

Когда ваши сообщения уже готовые использовать gettext, Ваш бот должен знати, как определить мову пользователя.

Поруч с мисцем инициализации диспетчера имеет быть созданный экземпляр перекладача:class:litegram.utils.i18n.I18n.

i18n = I18n(path="locales", default_locale="en", domain="messages")

После этого Вам нужно будет вибрати одну с встроенных промижних програм (middleware) I18n или написать власну.

Вбуквани промеждуни программы:

SimpleI18nMiddleware

class litegram.utils.i18n.middleware.SimpleI18nMiddleware(i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware')[исходный код]

Проси I18n middleware.

Вибирае код языки с об’еки User, отриманого в события.

__init__(i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware') None[исходный код]

Создания екземпляру промеждунои программы.

Параметры:
  • i18n – экземпляр I18n

  • i18n_key – ключ (название ключа) екземпляру I18n в контексти

  • middleware_key – контекстный ключ для этой промеждунои программы

ConstI18nMiddleware

class litegram.utils.i18n.middleware.ConstI18nMiddleware(locale: str, i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware')[исходный код]

Middleware Const вибирае ситично визначену локаль.

__init__(locale: str, i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware') None[исходный код]

Создания екземпляру промеждунои программы.

Параметры:
  • i18n – экземпляр I18n

  • i18n_key – ключ (название ключа) екземпляру I18n в контексти

  • middleware_key – контекстный ключ для этой промеждунои программы

FSMI18nMiddleware

class litegram.utils.i18n.middleware.FSMI18nMiddleware(i18n: I18n, key: str = 'locale', i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware')[исходный код]

Ця middleware зберигае локаль в сховищи FSM.

__init__(i18n: I18n, key: str = 'locale', i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware') None[исходный код]

Создания екземпляру промеждунои программы.

Параметры:
  • i18n – экземпляр I18n

  • i18n_key – ключ (название ключа) екземпляру I18n в контексти

  • middleware_key – контекстный ключ для этой промеждунои программы

async set_locale(state: FSMContext, locale: str) None[исходный код]

Запись новои локали в хранилище

Параметры:
  • state – экземпляр FSMContext

  • locale – нова локаль

I18nMiddleware

или визначте вашу власну промижну програму, основану на абстракции I18nMiddleware:

class litegram.utils.i18n.middleware.I18nMiddleware(i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware')[исходный код]

Абстракция промеждунои программы I18n

__init__(i18n: I18n, i18n_key: str | None = 'i18n', middleware_key: str = 'i18n_middleware') None[исходный код]

Создания екземпляру промеждунои программы.

Параметры:
  • i18n – экземпляр I18n

  • i18n_key – ключ (название ключа) екземпляру I18n в контексти

  • middleware_key – контекстный ключ для этой промеждунои программы

abstractmethod async get_locale(event: TelegramObject, data: dict[str, Any]) str[исходный код]

Визначення поточнои языки пользователя на основе события и контекста.

Этот метод должен быть перевизначеним в кчирних класах

Параметры:
  • event

  • data

Результат:

setup(router: Router, exclude: set[str] | None = None) BaseMiddleware[исходный код]

Реестрация промеждунои программы для всех событий в Роутери

Параметры:
  • router

  • exclude

Результат:

Працюемо с Babel

Шаг 1: Викбування текстив

pybabel extract --input-dirs=. -o locales/messages.pot

Где --input-dirs=.- шлях к коду, locales/messages.pot — это шаблон, куда будут извлекаться сообщения, а messages — домен перевода.

Working with plural forms

Extracting with Pybabel all strings options:

  • -k _:1,1t -k _:1,2 - for both singular and plural

  • -k __ - for lazy strings

pybabel extract -k _:1,1t -k _:1,2 -k __ --input-dirs=. -o locales/messages.pot

Примечание

Деяки корисни опции:

  • Для додавання коментарив для перекладачив, вы можете использовать инший тег, если хотите (TR) --add-comments=NOTE

  • Contact email for bugreport --msgid-bugs-address=EMAIL

  • Вимкнути коменири с розишуванням рядкив в коди --no-location

  • Copyrights --copyright-holder=AUTHOR

  • Всиновлення назви проекту --project=MySuperBot

  • Всиновлення версии --version=2.2

Шаг 2: Інициализация перевода

pybabel init -i locales/messages.pot -d locales -D messages -l en
  • -i locales/messages.pot - попередньо созданный шаблон

  • -d locales- тека переводов

  • -D messages - кмен переводов

  • -l en - язык. Может быть изменен на любой другой действительный код языка (Например -l ru для русского языка)

Шаг 3: Переклад текстив

Чтобы видкрити файл .po, вы можете использовать базовый текстовый редактор или будь-который редактор .po файлов, напр. Poedit

Просто видкрийте файл из названием locales/{language}/LC_MESSAGES/messages.po и впишить переводы

Шаг 4: Компиляция переводов

pybabel compile -d locales -D messages

Шаг 5: Оновлення текстив

Когда вы зминюете код свого бота, вам нужно обновить файлы .po и .mo

  • Шаг 5.1: отновлення файлу .pot: команда с кроку 1

  • Шаг 5.2: обновления .po файлов
    pybabel update -d locales -D messages -i locales/messages.pot
    
  • Шаг 5.3: обновления Ваших переводов: размещение и инструменты Ви знаете с кроку 3.

  • Шаг 5.4: компиляция .mo файлов : команда с кроку 4