babel-lsp
Language server for Python Babel i18n. Works with .py, Jinja templates, and .po/.pot catalog files.
Features
- Diagnostics — 32 checks across source files, PO catalogs, and the whole project
- Hover — translation table for any
_("msgid")call - Completion — msgid completion in translation calls
- Inlay hints — inline translation previews next to
_()calls - Code actions — remove fuzzy flags, fill missing translations, rename msgid across all files
- Go-to-definition / references / rename — treat msgids as first-class symbols
babel-lsp check— headless CLI linter, same rules as the LSP
Diagnostics
| Code | What it catches |
|---|---|
msg/empty-id |
_("") — empty string is the catalog header sentinel |
msg/fstring-in-call |
_(f"…") — f-string is interpolated before gettext sees it |
msg/format-before-call |
_("…" % x) — format applied before gettext |
msg/implicit-concat |
_("a" "b") — implicit string concatenation |
msg/non-constant-id |
_(variable) — pybabel cannot extract non-literal ids |
msg/unknown-id |
msgid not found in any catalog or template |
msg/missing-in-locale |
msgid translated in some locales but empty in others |
po/header-missing |
missing or incomplete catalog header |
po/duplicate-id |
same msgid appears twice in one file |
po/obsolete |
#~ entry absent from the .pot template |
po/missing-translation |
empty msgstr in a .po file |
po/fuzzy |
entry marked #, fuzzy |
po/blank |
msgstr is whitespace-only |
po/plural-count |
wrong number of plural forms vs. nplurals |
po/same-plurals |
all plural forms are identical |
po/format-mismatch |
printf/brace placeholder missing from translation |
po/extra-variable |
translation has extra placeholders not in source |
po/unchanged |
translation is identical to the source string |
po/newline-count |
\n count differs between source and translation |
po/whitespace-edges |
leading/trailing whitespace differs |
po/end-punctuation |
trailing punctuation differs |
po/double-space |
translation has double space not in source |
po/repeated-word |
consecutive repeated word in translation |
po/escape-mismatch |
backslash escape sequences differ |
po/bracket-count |
bracket count differs |
po/accelerator-mismatch |
& accelerator marker count differs |
po/xml-tag-mismatch |
XML/HTML tag structure differs |
po/url-changed |
URL from source is absent or path-altered |
po/number-mismatch |
numeric literals differ |
proj/inconsistent-translation |
same msgid translated differently in the same locale |
proj/missing-locale-file |
a locale has .po for some domains but not all |
proj/unused-id |
msgid exists in catalog but is never referenced in source |
Installation
uv tool install babel-lsp
Or with pip:
pip install babel-lsp
Or download a pre-built binary from the releases page.
Configuration
Place a babel-lsp.toml (or pyproject.toml [tool.babel-lsp] section) at your project root.
# Directories to search for .po/.pot files (auto-detected if absent)
locale_dirs = ["locale"]
# Default locale for features that need one
default_locale = "en"
# Restrict to specific translation domains
# domains = ["messages", "admin"]
# Additional translation functions beyond the built-ins
# (_, gettext, ngettext, pgettext, npgettext, lazy_gettext, …)
extra_keywords = ["my_gettext"]
# Extensions treated as Jinja templates
jinja_extensions = [".html", ".jinja", ".jinja2", ".j2"]
# Locale to show in inlay hints (defaults to first alphabetical locale)
# inlay_hint_locale = "de"
# Path to pybabel (auto-discovered on PATH if absent)
# pybabel_path = "/path/to/pybabel"
[diagnostics]
# Run only these checks (default: all)
# select = ["po/fuzzy", "po/missing-translation"]
# Suppress specific checks
ignore = ["po/unchanged", "po/same-plurals"]
# Override severity per code
[diagnostics.severity]
"po/fuzzy" = "warning"
"proj/unused-id" = "hint"
[unchanged]
# msgids to skip for po/unchanged (e.g. single-word proper nouns)
ignore = ["OK", "PDF"]
CLI
# Check the current project
babel-lsp check
# Check specific paths
babel-lsp check locale/ src/
# Run only selected checks
babel-lsp check --select po/fuzzy,po/missing-translation
# Suppress checks
babel-lsp check --ignore po/unchanged
# Auto-fix what can be fixed (fuzzy flags, missing translations)
babel-lsp check --fix
# Output formats: concise (default), full, json, json-lines, grouped,
# github, gitlab, junit, pylint
babel-lsp check --output-format github
# Exit 0 even with findings (useful in pre-commit hooks that only annotate)
babel-lsp check --exit-zero
Editor Setup
Zed
Install from the Zed extensions panel (Cmd+Shift+X) — search for babel-lsp and click Install. It activates automatically for Python files.
To control server order alongside other language servers, add to ~/.config/zed/settings.json:
{
"languages": {
"Python": { "language_servers": ["babel-lsp", "..."] }
}
}
Helix
Merge editors/helix/languages.toml into ~/.config/helix/languages.toml.
Neovim
Requires Neovim 0.11+. Add to your init.lua:
require("lspconfig").babel_lsp.setup {}
Or use the minimal snippet from editors/neovim/babel_lsp.lua.
Other editors
The server speaks standard LSP over stdio:
babel-lsp lsp --stdio
Fixtures
fixtures/ contains one minimal workspace per diagnostic code. Use them to verify diagnostics work or as templates for your own test setups:
babel-lsp check fixtures/po-fuzzy/
babel-lsp check fixtures/po-fuzzy/ --select po/fuzzy
Metadata
Release files for babel-lsp 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Actions Reset | |||
|---|---|---|---|---|
| babel_lsp-0.3.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details for babel_lsp-0.3.0-py3-none-win_amd64.whl |
| babel_lsp-0.3.0-py3-none-manylinux_2_28_x86_64.whl | Python 3 | none | Linux glibc 2.28+ x86-64 | Details for babel_lsp-0.3.0-py3-none-manylinux_2_28_x86_64.whl |
| babel_lsp-0.3.0-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details for babel_lsp-0.3.0-py3-none-manylinux_2_28_aarch64.whl |
| babel_lsp-0.3.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details for babel_lsp-0.3.0-py3-none-macosx_11_0_arm64.whl |
| babel_lsp-0.3.0-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details for babel_lsp-0.3.0-py3-none-macosx_10_12_x86_64.whl |
Total release size: 12.9 MB
Release files / babel_lsp-0.3.0-py3-none-win_amd64.whl
| Download URL | babel_lsp-0.3.0-py3-none-win_amd64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
cbdef3da5f869f74d07136ba3ee870f47799374af63a7354f06592f366caf87a
|
|
BLAKE2b-256 checksum How to use checksums |
fe7907141cf73836c477f7c5c4a034844b4803eb5abec3fd3f2e75be7ff9e683
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / babel_lsp-0.3.0-py3-none-manylinux_2_28_x86_64.whl
| Download URL | babel_lsp-0.3.0-py3-none-manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.7 MB |
| Tags | Linux glibc 2.28+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
ace71f58f52b312bfa94abf55ebb60b6ac05a9fa91db43d486d45d41fd5f2124
|
|
BLAKE2b-256 checksum How to use checksums |
61d426ab13eaa74e4ec4b62babe3812d94f5cc7153fc472ed4823a2060ae89b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / babel_lsp-0.3.0-py3-none-manylinux_2_28_aarch64.whl
| Download URL | babel_lsp-0.3.0-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
f2e3850f848935475ecf576ec1986f50fe0541f869f1d29187e9f97bf5db38bc
|
|
BLAKE2b-256 checksum How to use checksums |
488cf1f531ad78b4853301786add5195a64028a7a486aabb0008b3c29640f394
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / babel_lsp-0.3.0-py3-none-macosx_11_0_arm64.whl
| Download URL | babel_lsp-0.3.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
f5daf691591d35fdb3c5ae4da4e48334919fd1da26093976642e05fb9c64549a
|
|
BLAKE2b-256 checksum How to use checksums |
0fd80e137b332abdbb98fc0f481dc8accbb8a81b04c69aa8f83e34f5c869de95
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / babel_lsp-0.3.0-py3-none-macosx_10_12_x86_64.whl
| Download URL | babel_lsp-0.3.0-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.5 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
284678956b20dc9c7a0d99a97f8ca7ad5972397488a76787fbd6c40e792979cd
|
|
BLAKE2b-256 checksum How to use checksums |
d1afdb556adc612ec4ea6520b74c742f260ee7224af139ce488d8a0a02a87c7d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for babel-lsp 0.3.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.