mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
i18n: normalize Telegram region codes in locale detection
Resolve user locale by checking the Telegram language code as-is, then its Babel-normalized form, then the base language. This fixes lowercase regional codes such as pt-br failing to match available translations like pt_BR. Add tests covering region-code variants and fallback behavior, and update i18n documentation plus changelog notes.
This commit is contained in:
parent
73710acb4c
commit
53ad537739
4 changed files with 55 additions and 4 deletions
1
CHANGES/1755.bugfix.rst
Normal file
1
CHANGES/1755.bugfix.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Improved i18n locale detection in ``SimpleI18nMiddleware`` to support Telegram-style region codes such as ``pt-br`` by resolving first the raw code and then the normalized Babel-style code (for example ``pt_BR``).
|
||||
|
|
@ -129,14 +129,18 @@ class SimpleI18nMiddleware(I18nMiddleware):
|
|||
event_from_user: User | None = data.get("event_from_user")
|
||||
if event_from_user is None or event_from_user.language_code is None:
|
||||
return self.i18n.default_locale
|
||||
|
||||
user_locale = event_from_user.language_code
|
||||
try:
|
||||
locale = Locale.parse(event_from_user.language_code, sep="-")
|
||||
locale = Locale.parse(user_locale, sep="-")
|
||||
except UnknownLocaleError:
|
||||
return self.i18n.default_locale
|
||||
|
||||
if locale.language not in self.i18n.available_locales:
|
||||
return self.i18n.default_locale
|
||||
return locale.language
|
||||
for candidate in (user_locale, str(locale), locale.language):
|
||||
if candidate in self.i18n.available_locales:
|
||||
return candidate
|
||||
|
||||
return self.i18n.default_locale
|
||||
|
||||
|
||||
class ConstI18nMiddleware(I18nMiddleware):
|
||||
|
|
|
|||
|
|
@ -113,6 +113,16 @@ On top of your application the instance of :class:`aiogram.utils.i18n.I18n` shou
|
|||
|
||||
After that you will need to choose one of builtin I18n middleware or write your own.
|
||||
|
||||
When using :class:`aiogram.utils.i18n.middleware.SimpleI18nMiddleware`, locale codes from
|
||||
Telegram (for example ``pt-br``) are resolved against loaded locales in two steps:
|
||||
|
||||
1. Direct match as received from Telegram (``pt-br``)
|
||||
2. Normalized Babel-style identifier (``pt_BR``)
|
||||
|
||||
So if your translations are stored under
|
||||
``locales/pt_BR/LC_MESSAGES/messages.mo``, they will be selected for users with
|
||||
``language_code="pt-br"``.
|
||||
|
||||
Builtin middlewares:
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,42 @@ class TestSimpleI18nMiddleware:
|
|||
)
|
||||
assert locale == i18n.default_locale
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("available_locales", "default_locale", "language_code", "expected_locale"),
|
||||
[
|
||||
({"pt-br": None}, "en", "pt-br", "pt-br"),
|
||||
({"pt_BR": None}, "en", "pt-br", "pt_BR"),
|
||||
({"pt-br": None, "pt_BR": None}, "en", "pt-br", "pt-br"),
|
||||
({"en": None}, "uk", "en-US", "en"),
|
||||
({"uk": None}, "en", "uk-UA", "uk"),
|
||||
],
|
||||
)
|
||||
async def test_get_locale_region_code_variants(
|
||||
self,
|
||||
i18n: I18n,
|
||||
available_locales: dict[str, None],
|
||||
default_locale: str,
|
||||
language_code: str,
|
||||
expected_locale: str,
|
||||
):
|
||||
i18n.default_locale = default_locale
|
||||
middleware = SimpleI18nMiddleware(i18n=i18n)
|
||||
i18n.locales = available_locales
|
||||
|
||||
locale = await middleware.get_locale(
|
||||
None,
|
||||
{
|
||||
"event_from_user": User(
|
||||
id=42,
|
||||
is_bot=False,
|
||||
first_name="Test",
|
||||
language_code=language_code,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
assert locale == expected_locale
|
||||
|
||||
async def test_custom_keys(self, i18n: I18n):
|
||||
async def handler(event, data):
|
||||
return data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue