Internationalization middleware for aiogram.
aiogram_i18n adds locale-aware translation contexts to handlers, supports lazy translated
values in filters and keyboards, and lets you choose between Fluent and GNU gettext backends.
- Middleware for aiogram 3 routers and dispatchers.
- Fluent backends powered by
fluent.runtimeorfluent-compiler. - GNU gettext backend for compiled
.mocatalogs. - Lazy translation proxies for buttons, filters, and other delayed values.
- Locale managers for memory, FSM, Redis, constants, and custom storage.
- Stub generation for gettext catalogs (
.po,.pot,.mo).
Install the base package:
pip install aiogram-i18nChoose a backend:
# Fluent with fluent-compiler
pip install "aiogram-i18n[compiler]"
# Fluent with fluent.runtime
pip install "aiogram-i18n[runtime]"
# GNU gettext uses Python's stdlib gettext module
pip install aiogram-i18nCreate Fluent locale files:
locales/
en/
LC_MESSAGES/
bot.ftl
uk/
LC_MESSAGES/
bot.ftl
Example locales/en/LC_MESSAGES/bot.ftl:
hello = Hello, <b>{ $user }</b>!
help = HelpUse the middleware in your bot:
import asyncio
from contextlib import suppress
from logging import INFO, basicConfig
from typing import Any
from aiogram import Bot, Dispatcher, Router
from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode
from aiogram.filters import CommandStart
from aiogram.types import Message
from aiogram_i18n import I18nContext, I18nMiddleware, LazyProxy
from aiogram_i18n.cores import FluentRuntimeCore
from aiogram_i18n.lazy.filter import LazyFilter
from aiogram_i18n.types import KeyboardButton, ReplyKeyboardMarkup
router = Router(name=__name__)
keyboard = ReplyKeyboardMarkup(
keyboard=[[KeyboardButton(text=LazyProxy("help"))]],
resize_keyboard=True,
)
@router.message(CommandStart())
async def cmd_start(message: Message, i18n: I18nContext) -> Any:
name = message.from_user.mention_html()
return message.answer(
text=i18n.get("hello", user=name),
reply_markup=keyboard,
)
@router.message(LazyFilter("help"))
async def cmd_help(message: Message) -> Any:
return message.answer(text=message.text)
async def main() -> None:
basicConfig(level=INFO)
bot = Bot("42:ABC", default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp = Dispatcher()
dp.include_router(router)
i18n = I18nMiddleware(
core=FluentRuntimeCore(path="locales/{locale}/LC_MESSAGES"),
default_locale="en",
)
i18n.setup(dispatcher=dp)
await dp.start_polling(bot)
if __name__ == "__main__":
with suppress(KeyboardInterrupt):
asyncio.run(main())Handlers can receive I18nContext through aiogram dependency injection:
@router.message(CommandStart())
async def handler(message: Message, i18n: I18nContext) -> None:
await message.answer(i18n.get("hello", user=message.from_user.full_name))You can also use attribute-style keys. The default separator is -, so
i18n.profile.title() resolves profile-title.
text = i18n.profile.title(user="Andrew")For lazy values, use LazyProxy or the built-in factory:
from aiogram_i18n import L, LazyProxy
LazyProxy("help")
L.profile.title(user="Andrew")Lazy values are useful in filters, keyboards, and objects that are rendered after the locale is
known. Import mutable aiogram types from aiogram_i18n.types when they contain lazy values.
Runtime Fluent backend based on fluent.runtime.
from aiogram_i18n.cores import FluentRuntimeCore
core = FluentRuntimeCore(path="locales/{locale}/LC_MESSAGES")Install it with:
pip install "aiogram-i18n[runtime]"Compiled Fluent backend based on fluent-compiler.
from aiogram_i18n.cores import FluentCompileCore
core = FluentCompileCore(path="locales/{locale}/LC_MESSAGES")Install it with:
pip install "aiogram-i18n[compiler]"GNU gettext backend for .mo files.
from aiogram_i18n.cores import GNUTextCore
core = GNUTextCore(path="locales/{locale}/LC_MESSAGES")Expected layout:
locales/
en/
LC_MESSAGES/
bot.mo
The middleware stores and reads the current locale through a manager. By default it uses
MemoryManager.
i18n = I18nMiddleware(
core=FluentRuntimeCore(path="locales/{locale}/LC_MESSAGES"),
default_locale="en",
)To persist locales elsewhere, pass another manager:
from aiogram_i18n.managers import FSMManager
i18n = I18nMiddleware(
core=FluentRuntimeCore(path="locales/{locale}/LC_MESSAGES"),
manager=FSMManager(),
)The package exposes an i18n command.
Generate Python stubs from gettext catalogs:
i18n stub -i locales/en/LC_MESSAGES/bot.po -o stubs/i18n.pyiSupported stub inputs are .po, .pot, and .mo. The parser uses polib, so install it if your
environment does not already provide it:
pip install polibFTL extraction and FTL stub generation are handled by FTL-Extract:
pip install ftl-extractFull documentation is available at aiogram-i18n.readthedocs.io.
aiogram_i18n is distributed under the MIT license.