🌍
i18n, l10n - мови у боті #цікаве
👉 i18n (internationalization) - процес, який надає можливість використовувати програмам кілька мов. l10n (localization) - більш конкретні дії, спрямовані на використання готових інструментів для роботи з мовами і адаптацію до мовних культур
📌 Обрано саме 18 і 10, бо це просто кількість літер між крайніми буквами (а повні слова всім лінь писати)
😀
І навіщо мені цим користуватись?• багатьом людям приємніше працювати зі своєю рідною мовою, це покращує користувацький досвід
• знаючи те, які мови обирають користувачі можна більш точно показувати їм те, що треба саме нам (кому буде приємно бачити рекламу мовою, яку ми не знаємо?)
👀 Як цим користуватись?
1️⃣
ІнструментиПочнемо з того, що нам треба працювати саме з ботом. На даний момент є такі інструменти:
• вбудований
aiogram.utils.i18n (на основі GNU gettext і Babel)
• неофіційна
aiogram_i18n від активного учасника спільноти Patrick (підтримує GNU gettext, але пріоритет на Project Fluent)
Думаю, легше буде почати з aiogram_i18n, та і виглядає вона перспективніше.
📌 GNU gettext був створений у 1995 р,
детальніше (багато цікавого загалом). Project Fluent - у 2019, це дослідницький проект Mozilla. Він був створений для вирішення багатьох проблем i18n/l10n,
детальніше.
2️⃣
Як працює aiogram_i18nПростими словами її роботу можна описати так:
• при отриманні апдейту бібліотека за допомогою менеджера отримує код мови користувача (en, uk)
• спеціальний мідлвар користується цим менеджером і за допомогою
Dependency Injection передає екземпляр I18nContext як i18n (назву можна змінити) у ланцюг до інших мідлварів, що стоять нижче, фільтрів і нарешті хендлерів
• в екземплярі вже визначена мова (
локаль) користувача, тому за допомогою I18nContext в хендлері можна діставати відповідні переклади чи змінювати локаль юзера за замовчуванням
3️⃣
Звідки і який менеджер бере локальЯкщо у нас локалі знаходяться в БД, то треба створити менеджер самостійно як підклас
aiogram_i18n.managers.base.BaseManager
В ньому треба буде реалізувати два методи get_locale і set_locale. Проте необов'язково реалізовувати свій менеджер - у бібліотеці є готові рішення на основі
Memory/Redis/FSM. Отже, задача менеджера допомагати мідлвару отримувати локаль тим способом який ми йому «показали»
4️⃣
get_locale і set_locale• Що повинен повертати метод get_locale?
» Просто назву коду мови, наприклад "en" чи "de". Ці коди повинні бути назвами директорій з перекладами, про це пізніше.
• Для чого set_locale?
» Буде логічно, якщо все, що пов'язано з перекладом, буде виконувати I18nContext - в тому числі і зміну локалі юзера
Доволі простий приклад:
class i18nManager(BaseManager):
user_languages = {}
async def get_locale(self, event_from_user: User, db: Database) -> str:
try:
return self.user_languages[event_from_user.id]
except KeyError:
language = await db.get_user_language(event_from_user.id)
self.user_languages[event_from_user.id] = language
return language
async def set_locale(self, locale: str, event_from_user: User, db: Database) -> None:
await db.set_user_language(event_from_user.id, locale)
self.user_languages[event_from_user.id] = locale
📌 Зверни увагу, що в set_locale перший позиційний аргумент це locale
5️⃣
Підключення та оформлення• Імпортуємо і реєструємо I18nMiddleware
• В аргументах як ядро вказуємо FluentRuntimeCore (pip install fluent.runtime). Я обрав це, бо зараз доступні 3 ядра, чув що FluentCompileCore хочуть прибрати, а GNU gettext є і в build-in
• В аргументи мідлвара передаємо потрібний нам менеджер (чи самописний)
• Далі вказуємо директорії з перекладами. Їх приклади дивись в
репозиторіях. Головне правильный шаблон шляху і розподілені .ftl файли
• Про синтаксис .ftl файлів
читай тут• Тепер використовуй у хендлерах i18n.get і якщо хочеш роби
стаби📌 LazyProxy - це фільтр, що сам дістає відповідний переклад і порівнює його із вхідним текстом
⭐️
aiogram_i18n