Linter for localization files (.po, .ts)
Project description
l10n-lint
🔍 Linter for localization files (.po, .ts) — CLI and GTK interfaces
Check your translation files for common issues like missing translations, fuzzy entries, placeholder mismatches, and more.
Version: 1.14.9 (CLI) / 1.2.9 (GTK)
Features
Core checks
- Missing translations – Find empty
msgstrentries - Fuzzy entries – Flag translations needing review
- Placeholder mismatches – Detect
%s,{0},%1inconsistencies - Duplicate entries – Find repeated
msgidentries
Typography & formatting
- Inconsistent punctuation – Missing or mismatched ending punctuation
- Inconsistent capitalization – First letter case mismatch
- Whitespace issues – Trailing spaces, double spaces
- Mixed quotes – Inconsistent quote styles (
"vs"vs„)
Technical
- HTML tag mismatch –
<b>,<a href>tags don't match - Escaped chars mismatch –
\n,\t,\\inconsistencies - Keyboard accelerators – Missing or mismatched
&shortcuts - Numeric mismatch – Numbers from source missing in translation
Quality
- Untranslated words – Common English words left in translation
- Repeated words – "and and", "the the"
- Source equals translation – Possibly forgotten to translate
- Suspicious length – Translation too short or too long
Additional features
- GitHub support – Lint repos directly without cloning
- Localized output – Available in 45+ languages
- CI mode – Exit code only with
--check - Quiet mode – Summary only with
-q
GTK Interface (l10n-lint-gtk)
Modern GTK4/libadwaita graphical interface with:
- 🎛️ Lint rule preferences – Enable/disable individual checks
- 📋 File metadata panel – Language, translator, revision date, project info
- 📊 Statistics – Entries, translated, untranslated, fuzzy counts
- 🔍 Filter & search – By severity, rule type, or text
- 🖱️ Drag & drop – Drop files to lint automatically
- 📤 Export reports – HTML, JSON, or plain text
- ⌨️ Keyboard shortcuts – Ctrl+O, Ctrl+Return, Ctrl+E
- 🌍 Localized – 45+ languages
Installation
Debian/Ubuntu (APT)
# Add GPG key
curl -fsSL https://yeager.github.io/debian-repo/yeager.gpg | sudo gpg --dearmor -o /usr/share/keyrings/yeager.gpg
# Add repository
echo 'deb [signed-by=/usr/share/keyrings/yeager.gpg] https://yeager.github.io/debian-repo stable main' | sudo tee /etc/apt/sources.list.d/yeager.list
# Install
sudo apt update
sudo apt install l10n-lint # CLI only
sudo apt install l10n-lint-gtk # GTK interface (includes CLI)
Fedora/RHEL (DNF)
sudo tee /etc/yum.repos.d/yeager.repo << 'EOF'
[yeager]
name=Yeager's Translation Tools
baseurl=https://yeager.github.io/rpm-repo
enabled=1
gpgcheck=0
EOF
sudo dnf install l10n-lint
From source
git clone https://github.com/yeager/l10n-lint.git
cd l10n-lint
chmod +x l10n_lint.py l10n_lint_gtk.py
# CLI
ln -s $(pwd)/l10n_lint.py ~/.local/bin/l10n-lint
# GTK (requires: python3-gi, gir1.2-gtk-4.0, gir1.2-adw-1)
ln -s $(pwd)/l10n_lint_gtk.py ~/.local/bin/l10n-lint-gtk
Usage
CLI
# Lint a directory
l10n-lint ./translations/
# Lint a single file
l10n-lint messages.po
# GitHub repository
l10n-lint --github owner/repo
# JSON output
l10n-lint --format json ./translations/
# GitHub Actions annotations
l10n-lint --format github --strict ./translations/
GTK
l10n-lint-gtk # Launch GUI
l10n-lint-gtk messages.po # Open file directly
Or drag and drop files onto the window!
Options
| Option | Description |
|---|---|
--github, -g |
GitHub repository (owner/repo or URL) |
--path, -p |
Path filter for GitHub repos |
--format, -f |
Output format: text, json, github |
--max-length |
Max translation length (default: 500) |
--no-recursive |
Don't search subdirectories |
--strict |
Treat warnings as errors |
-q, --quiet |
Summary only |
Supported formats
| Format | Extension | Description |
|---|---|---|
| gettext | .po |
GNU gettext translation files |
| Qt | .ts |
Qt Linguist translation files |
Lint rules
| Rule | Severity | Description |
|---|---|---|
missing-translation |
❌ Error | Empty msgstr / unfinished translation |
fuzzy |
⚠️ Warning | Translation flagged as fuzzy |
placeholder |
❌ Error | Placeholder mismatch (%s, {0}, etc.) |
duplicate |
⚠️ Warning | Duplicate msgid entry |
length |
⚠️ Warning | Translation length ratio too high |
punctuation |
ℹ️ Info | Ending punctuation mismatch |
capitalization |
ℹ️ Info | Initial letter case mismatch |
whitespace |
⚠️ Warning | Leading/trailing whitespace issues |
html-tags |
❌ Error | HTML tags don't match |
escapes |
❌ Error | Escape sequences mismatch |
accelerators |
⚠️ Warning | Keyboard accelerator issues |
numerics |
ℹ️ Info | Numbers not preserved |
untranslated |
ℹ️ Info | English words in translation |
repeated-words |
ℹ️ Info | Duplicated words |
source-equals-translation |
ℹ️ Info | Translation same as source |
Examples
CI/CD Integration
# GitHub Actions
- name: Lint translations
run: |
pip install l10n-lint
l10n-lint --format github --strict ./translations/
Find specific issues
# Missing translations only
l10n-lint ./po/ | grep missing-translation
# JSON for scripting
l10n-lint --format json ./po/ | jq '.issues[] | select(.severity == "error")'
Exit codes
| Code | Meaning |
|---|---|
| 0 | No errors (warnings allowed) |
| 1 | Errors found (or warnings with --strict) |
Requirements
CLI:
- Python 3.8+
- No external dependencies (stdlib only)
GTK:
- Python 3.8+
- GTK 4.0, libadwaita 1.0
- PyGObject (
python3-gi)
License
GPL-3.0-or-later
Author
Daniel Nylander (@yeager)
Part of Yeager's Translation Tools
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 Distribution
Built Distribution
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 l10n_lint-1.15.0.tar.gz.
File metadata
- Download URL: l10n_lint-1.15.0.tar.gz
- Upload date:
- Size: 31.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c0b3f3fa8f7b268abc5e2f9323dbefff507d1a738419bea9d00e4c18170797d2
|
|
| MD5 |
4e06d34fef83ce9c2325274a6c3e8d7b
|
|
| BLAKE2b-256 |
3f3713c52182c6b1b8cc128c1a3836526c8282fc22b6f1b0ec4b476c9d0b8cf9
|
File details
Details for the file l10n_lint-1.15.0-py3-none-any.whl.
File metadata
- Download URL: l10n_lint-1.15.0-py3-none-any.whl
- Upload date:
- Size: 32.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cfcb7d308f7493b72f254f121523181ffa421e4351ee8f86db730026cf307e6
|
|
| MD5 |
1eb574df819ee7f804716bb5f6b1dd5e
|
|
| BLAKE2b-256 |
a8df9ca3bf06817e62d9249a13d49ac24e989b9adc98d74b89195dbc0b3caca2
|