aiogram_i18n with Fluent/FTL
This reference covers runtime usage of aiogram_i18n for aiogram 3.
Primary sources:
- Context7 aiogram_i18n library:
/aiogram/i18n - Context7 aiogram 3 library:
/aiogram/aiogram/v3.25.0 - GitHub: https://github.com/aiogram/i18n
- PyPI: https://pypi.org/project/aiogram_i18n/
Use Context7 first for exact examples and current API shape, then fall back to GitHub or PyPI when you need package prose or details that are not covered in snippets.
Installation
Base package:
pip install aiogram_i18nFor Fluent Runtime:
pip install fluent.runtimeFor Fluent Compile Core:
pip install fluent_compilerCore setup
The documented basic runtime setup uses I18nMiddleware with FluentRuntimeCore.
Minimal shape:
from aiogram import Bot, Dispatcher, Router
from aiogram_i18n import I18nContext, I18nMiddleware
from aiogram_i18n.cores.fluent_runtime_core import FluentRuntimeCore
router = Router()
i18n_middleware = I18nMiddleware(
core=FluentRuntimeCore(
path="locales/{locale}/LC_MESSAGES"
)
)
dp = Dispatcher()
dp.include_router(router)
i18n_middleware.setup(dispatcher=dp)This registration pattern is shown in the project README/PyPI description.
Locale file layout
For Fluent Runtime, the documented path shape is:
locales/
en/
LC_MESSAGES/
messages.ftl
uk/
LC_MESSAGES/
messages.ftlThe exact FTL file name is project-defined, but the locale directory structure should match the configured path template.
Handler usage
Handlers can receive I18nContext directly and render strings through:
i18n.get("key", arg=value)i18n.key(arg=value)
Example:
@router.message(...)
async def handler(message: Message, i18n: I18nContext) -> None:
await message.answer(i18n.get("hello", user=message.from_user.full_name))Lazy translations
The documented package also exposes:
LazyProxyLazyFilter
Useful cases:
- localized keyboard button labels
- matching localized button text in filters
Important package note from the docs:
- if you use
LazyProxyinside mutable Telegram objects, import those mutable objects fromaiogram_i18n.types
Locale persistence pattern
aiogram_i18n is the runtime i18n layer. Your project still needs to decide how locale is stored.
A universal pattern is:
- resolve target locale from callback data, command args, profile, or Telegram user language
- persist locale in your own storage layer
- call
await i18n.set_locale(...) - re-render the current screen in the new locale
Use scripts/i18n_callback_query.py for the handler shape.
Extraction and generation workflow
aiogram_i18n itself is the runtime layer. Extraction and locale-file generation usually come from a separate tool.
One concrete FTL-oriented tool is FTL-Extract:
- PyPI: https://pypi.org/project/FTL-Extract/
- command:
ftl_extract
Example usage from the published tool docs:
pip install FTL-Extract
ftl_extract project_path/code_path project_path/localesThe same tool also documents multi-locale extraction, for example:
ftl_extract project_path/code_path project_path/locales -l en -l uk -l plAnd custom i18n key discovery, for example:
ftl_extract project_path/code_path project_path/locales -k i18n -k LazyProxy -k LImportant boundary:
- this command comes from
FTL-Extract, not fromaiogram_i18n - if a repository uses another extractor or a wrapper command, document that repository-specific command separately
- do not present a project wrapper as universal unless it is actually part of the chosen toolchain
Minimal FTL example
hello = Hello, { $user }!
language-select-prompt = Choose your language.
language-changed-success = Language updated.Practical rules
- keep keys stable and semantic
- re-render UI after locale changes
- avoid hard-coded English strings in callbacks
- treat locale storage and locale rendering as separate concerns