Language server for Python Babel i18n
Project description
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 the bundled extension:
just install-zed
Then 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file babel_lsp-0.1.6-py3-none-win_amd64.whl.
File metadata
- Download URL: babel_lsp-0.1.6-py3-none-win_amd64.whl
- Upload date:
- Size: 2.7 MB
- Tags: Python 3, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f17bfa90f117227456dfce64f8099e96345937efe2236b794091c1637622969
|
|
| MD5 |
5987fac27f6842709be7ca41dc41ae0c
|
|
| BLAKE2b-256 |
94fe7920b2e61f93ac45eaec4a816690153b95b4530357a386fb6587c05dba6e
|
File details
Details for the file babel_lsp-0.1.6-py3-none-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: babel_lsp-0.1.6-py3-none-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.7 MB
- Tags: Python 3, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7d59d2ed12943429852ad00df7190916c349b24ed08e7d1e2c697450ee55577
|
|
| MD5 |
70309bd73341bcba5cb4f4a57d4e5a02
|
|
| BLAKE2b-256 |
f6b35fbfe5548c10ba35eccc1aff75baab33625c6cd02f400088e48841021890
|
File details
Details for the file babel_lsp-0.1.6-py3-none-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: babel_lsp-0.1.6-py3-none-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 2.6 MB
- Tags: Python 3, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6ffc76a75eb9567c1fdb994f42abab47768faac45741e74cf0c99b696899f9e1
|
|
| MD5 |
da4b6a05e0391afb53d13c272461a5b3
|
|
| BLAKE2b-256 |
ee449305680bc7ff33adf0b66e0fd2b41ab9b812cd4013024b1f110d01330f6a
|
File details
Details for the file babel_lsp-0.1.6-py3-none-macosx_11_0_arm64.whl.
File metadata
- Download URL: babel_lsp-0.1.6-py3-none-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.5 MB
- Tags: Python 3, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7634967cf13b92146f495df9a5f24f4988777146b56683bc07e5571165efae2
|
|
| MD5 |
dca37a3b8960444a8010d42e2072e1e5
|
|
| BLAKE2b-256 |
7c71ad36aad28912f18de866405bbbb37c841a9060fbfaafcc475844a6e8d529
|
File details
Details for the file babel_lsp-0.1.6-py3-none-macosx_10_12_x86_64.whl.
File metadata
- Download URL: babel_lsp-0.1.6-py3-none-macosx_10_12_x86_64.whl
- Upload date:
- Size: 2.6 MB
- Tags: Python 3, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb8220d99507d9d6a930cb8fc77e53fb648fa9b58a5167799eb0ed68d269f0ad
|
|
| MD5 |
df5a84f6fd019760cd9e687358b3961e
|
|
| BLAKE2b-256 |
f40734415edafa25bb4a68a194241ecce7d59b69a6d3809db1a6cc739b7fac9a
|