Skip to main content

starlette-i18n

Request-safe gettext localization and locale negotiation for Starlette applications.

Requirements

  • Python 3.11+ (CI validates Python 3.11, 3.12, 3.13, and 3.14)
  • Starlette newer than 1.2.0 and below 2.0

Install

uv add starlette-i18n
pip install starlette-i18n

Quick start

Compile gettext catalogs before starting the application, then load them once:

from starlette.applications import Starlette
from starlette.responses import PlainTextResponse

from starlette_i18n import LocaleMiddleware, TranslationCatalog, gettext

catalog = TranslationCatalog.load("locales", domain="messages", default_locale="en")
app = Starlette()
app.add_middleware(LocaleMiddleware, catalog=catalog)


async def homepage(request):
    return PlainTextResponse(gettext("Success"))


app.add_route("/", homepage)

The selected Locale is also available as request.state.locale. The public translation helpers are gettext, ngettext, gettext_lazy, and get_locale.

Locale selection

LocaleMiddleware selects one catalog for each HTTP request in this order:

  1. A valid configured locale cookie (locale by default).
  2. The request's Accept-Language header.
  3. The catalog's configured default locale.

Header values are parsed as a q-weighted priority list and resolved using RFC 4647 lookup. Exact complex tags work: a zh-CN request selects a zh_CN catalog directory, while pt-BR can fall back to a pt catalog. Invalid values and q=0 entries are ignored. A wildcard falls back to the configured default when no explicit supported locale matches.

Responses include Content-Language. The middleware adds configured selection inputs (Cookie and Accept-Language by default) to Vary so shared caches do not serve the wrong representation.

Configure another cookie name, or disable cookies entirely:

app.add_middleware(LocaleMiddleware, catalog=catalog, cookie_name="language")
app.add_middleware(LocaleMiddleware, catalog=catalog, cookie_name=None)

ASGI and Jinja safety

The active locale is stored in a ContextVar and is reset after every request, including exceptions. Concurrent requests therefore cannot leak translations into one another.

Do not install gettext functions into a shared Jinja environment per request: Jinja's installation mutates global environment state. Pass a request-local callable instead:

html = template.render(request=request, _=request.state.locale.translate)

Then use {{ _("Success") }} in the template. See examples/jinja_app.py.

Examples

uv run --with uvicorn examples/basic_usage.py
uv run --with 'uvicorn[standard]' uvicorn examples.uvicorn_runner:app --reload
uv run --with gunicorn --with uvicorn gunicorn -c examples/gunicorn_conf.py examples.gunicorn_runner:app
curl -H 'Accept-Language: ru' http://127.0.0.1:8000/

Migrating from 2.x

3.0 is a breaking release. It requires Python 3.11+, moves the package to src/, uses pyproject.toml and uv, and replaces LocaleDefaultMiddleware, LocaleFromCookieMiddleware, LocaleFromHeaderMiddleware, and the old ordering-dependent LocaleMiddleware with the single LocaleMiddleware shown above. Load catalogs with TranslationCatalog.load() instead of load_gettext_translations().

Further documentation

Development

uv sync --all-groups
make lint
make test
make build

License

starlette-i18n is distributed under the Apache License 2.0. Report vulnerabilities through the security policy.

Release files for starlette-i18n 3.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for starlette-i18n 3.0.0
File Size Uploaded
starlette_i18n-3.0.0.tar.gz 64.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for starlette-i18n 3.0.0
File Interpreter ABI Platform
starlette_i18n-3.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 77.4 kB

Release files / starlette_i18n-3.0.0.tar.gz

Download URL starlette_i18n-3.0.0.tar.gz
Size 64.9 kB
Tags Source
SHA-256 checksum
How to use checksums
af4557c07158b6b785ba6b18bff108ef4a914f041f9ac52cb424cab85a76880f
BLAKE2b-256 checksum
How to use checksums
b0991c82ee6457fce547fc1d87cd6be92a5dd6f6f12a9154754c28d67cf6e440
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.

Transparency log

Release files / starlette_i18n-3.0.0-py3-none-any.whl

Download URL starlette_i18n-3.0.0-py3-none-any.whl
Size 12.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
62319160d97090736abb888d7f4bc2e3218b5599dc6515916145dc5d3da7654a
BLAKE2b-256 checksum
How to use checksums
0d9e20630439800ad775b17766f9ed93f393a37812104f052c2da8b150d02828
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

3.0.0 This release

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.0.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.4.0

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page