wagtail-localize-intentional-blanks
A Wagtail library that extends wagtail-localize to allow translators to mark translation segments as "do not translate". These segments count as translated (contributing to progress) but fall back to the source page's value when rendered.
Features
- ✅ Translator Control: Translators decide which fields to not translate
- ✅ Per-Locale Flexibility: One language can translate a value while another language can use the source value
- ✅ Progress Tracking: "Do not translate" segments count as translated by
wagtail-localize - ✅ No Template Changes: Works transparently with existing templates
- ✅ Drop-in Integration: Minimal code changes required
- ✅ UI Included: Adds "Do Not Translate" buttons to translation editor
Installation
pip install wagtail-localize-intentional-blanks
Quick Start
1. Add to INSTALLED_APPS
Important: wagtail_localize_intentional_blanks must come before wagtail_localize in INSTALLED_APPS for template overrides to work.
# settings.py
INSTALLED_APPS = [
# ... other apps
'wagtail_localize_intentional_blanks', # Must be BEFORE wagtail_localize
'wagtail_localize',
'wagtail_localize.locales',
# ... other apps
]
2. Include URLs
# urls.py
from django.urls import path, include
urlpatterns = [
# ... other patterns
path(
'intentional-blanks/', include('wagtail_localize_intentional_blanks.urls')
),
]
That's it! The "Do Not Translate" button will now appear in the translation editor for all translatable fields. No code changes to your blocks or models required.
How It Works
This library works by:
- Adding UI controls - JavaScript adds "Do Not Translate" checkboxes to the translation editor
- Storing markers - When checked, a marker string (
__DO_NOT_TRANSLATE__) is stored in the translation - Automatic replacement - When rendering pages, a patch intercepts segment retrieval and replaces markers with source values
- Progress tracking - Marked segments count as "translated" for progress calculation
Key benefit: No code changes to your blocks or models. The library handles everything automatically through patching wagtail-localize's internal methods.
Usage
In the Translation Editor
- Open a page translation in wagtail-localize's editor
- For each segment, you'll see a "Mark 'Do Not Translate'" checkbox
- Check it to mark that segment as do not translate
- The segment counts as translated (shows green)
- When the page renders, it automatically shows the source value for that field
- If the value in the original page changes, and the translated pages are synced, the segment still counts as translated (shows green) and when the page renders, it shows the updated source value for that field
Common Use Cases
- Brand names and trademarks - Keep consistent across locales
- Product codes and SKUs - No translation needed
- URLs - Pages may contain the translations for different languages, but a URL is the same for all languages
- IDs - Not language-specific identifiers
Configuration
You can customize behavior in your Django settings:
# settings.py
# Enable/disable the feature globally
WAGTAIL_LOCALIZE_INTENTIONAL_BLANKS_ENABLED = True
# Custom marker (advanced)
WAGTAIL_LOCALIZE_INTENTIONAL_BLANKS_MARKER = "__DO_NOT_TRANSLATE__"
# Require specific permission (default: None = any translator)
WAGTAIL_LOCALIZE_INTENTIONAL_BLANKS_REQUIRED_PERMISSION = 'cms.can_mark_do_not_translate'
Advanced Usage
Programmatic API
You can programmatically mark segments as "do not translate" using the provided utilities:
from wagtail_localize_intentional_blanks.utils import (
mark_segment_do_not_translate,
unmark_segment_do_not_translate,
get_source_fallback_stats,
)
from wagtail_localize.models import Translation, StringSegment
# Mark a segment
translation = Translation.objects.get(id=123)
segment = StringSegment.objects.get(id=456)
mark_segment_do_not_translate(translation, segment, user=request.user)
# Unmark a segment
unmark_segment_do_not_translate(translation, segment)
# Get statistics
stats = get_source_fallback_stats(translation)
print(f"{stats['do_not_translate']} segments marked as do not translate")
print(f"{stats['manually_translated']} segments manually translated")
Requirements
- Python 3.10+
- Django 4.2+
- Wagtail 5.2+
- wagtail-localize 1.8+
Release
In order to make a release, we add a git tag and push it to GitHub. We have a GitHub Action that releases the code to PyPI when we add a new tag.
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome!
Development
Setting Up for Development
- Clone the repository:
git clone https://github.com/lincolnloop/wagtail-localize-intentional-blanks.git
cd wagtail-localize-intentional-blanks
- Install the package with development dependencies:
pip install -e ".[dev]"
This installs the package in editable mode along with testing tools (pytest, black, flake8, etc.).
Running Tests
Run the test suite with pytest:
pytest
Run tests with coverage:
pytest --cov=wagtail_localize_intentional_blanks
Run specific test files:
pytest tests/test_utils.py
pytest tests/test_views.py
Code Quality
Check code with ruff:
ruff check .
Format with ruff:
ruff format .
Credits
Created by Lincoln Loop, LLC for the Wagtail community.
Metadata
Release files for wagtail-localize-intentional-blanks 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| wagtail_localize_intentional_blanks-0.3.0.tar.gz | 47.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| wagtail_localize_intentional_blanks-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 81.9 kB
Release files / wagtail_localize_intentional_blanks-0.3.0.tar.gz
| Download URL | wagtail_localize_intentional_blanks-0.3.0.tar.gz |
|---|---|
| Size | 47.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
53eba5279eba730a75a98ad27729405b45871a8411f88542c7f774f2295538f5
|
|
BLAKE2b-256 checksum How to use checksums |
e1cc5c3518dd96960db89341ac40a7ec3a090c2dc77abdf0cc5ab413c8810f94
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Mar 5, 2026.
Transparency logRelease files / wagtail_localize_intentional_blanks-0.3.0-py3-none-any.whl
| Download URL | wagtail_localize_intentional_blanks-0.3.0-py3-none-any.whl |
|---|---|
| Size | 34.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc16f86978671315f17ff1d9a3333592fd136f028fce290a7aa6db493a0e10d6
|
|
BLAKE2b-256 checksum How to use checksums |
e20e4bd8cbdce234c20cb23fc85f2089e9a82601fc8800dafe74eab7bd99759f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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 Mar 5, 2026.
Transparency log