Taming Weblate's Git Sync: When Translations Actually Reach Your Repository
Weblate stages translations locally before committing to Git. The commit_pending and push_on_commit settings control when those changes become visible — and how noisy your repository history gets.
24 Jul 2025, 12:57 UTC

The problem: translations stuck in limbo
You merge a pull request that adds a new language, but the translated strings don't appear in the repository. Or worse, your CI pipeline triggers on every single typo fix because Weblate pushes a commit for each keystroke. Both symptoms trace back to the same place: Weblate's commit_pending and push_on_commit settings.
Weblate doesn't write translator edits directly to your Git repository. Instead, it stages them as pending commits in its internal database. Two knobs control when those staged changes become real Git history:
- commit_pending — after how many changes or how much time Weblate creates a local commit.
- push_on_commit — whether that commit is immediately pushed to the upstream remote.
Misconfigure these and you either drown maintainers in micro-commits or leave translators wondering why their work isn't visible downstream.
How Weblate buffers changes
When a translator saves a string in Weblate's UI, the change lands in Weblate's database, not in the working tree of the cloned repository. This design lets Weblate offer features like translation memory, glossary lookups, and conflict-free concurrent editing without locking the Git repo.
The commit_pending setting defines the flush trigger. You can configure it as:
- A number of pending changes (e.g., "commit after 5 edits")
- A time interval (e.g., "commit changes older than 30 minutes")
- Both — whichever threshold is reached first
Until that trigger fires, the translations exist only in Weblate. External tools reading the repository directly — CI jobs, documentation builders, other developers — see stale strings.
commit_pending: controlling commit granularity
A low threshold (1 change, 1 minute) creates a commit per edit. That's fine for a personal project but noisy for a team repository. Each commit appears in git log, triggers CI, and clutters bisect history.
A high threshold (50 changes, 24 hours) batches work neatly but introduces latency. A critical typo fix might sit invisible for hours.
Most teams settle on a middle ground: commit after 10–20 changes or 1–2 hours, whichever comes first. This batches routine edits while still surfacing urgent fixes within a reasonable window.
push_on_commit: the visibility switch
With push_on_commit enabled, every local commit Weblate creates is immediately pushed to the configured upstream remote (usually origin). Downstream consumers see changes fast, but you also get:
- More CI runs — each push triggers pipelines
- Potential merge conflicts if someone force-pushes or rewrites history on the translation branch
- Authentication failures leaving commits stranded in Weblate
With push_on_commit disabled, commits accumulate locally. You (or a scheduled job) must run git push from Weblate's repository to publish them. This gives you a chance to squash, review, or coordinate — but translations stay invisible until you act.
Worked example: CI-friendly batching for a Django project
Suppose your Django project uses Weblate for 12 languages. The translation branch is i18n/main. CI runs on every push to that branch and takes 8 minutes. You want translations visible within an hour but don't want 50 CI runs per day.
Configuration via Weblate admin UI:
- Navigate to Components → your-component → Settings → Version control.
- Set Commit pending changes after to
15(changes). - Set Age of changes to commit to
60(minutes). - Enable Push on commit.
- Save.
Equivalent REST API call (requires admin token):
curl -X PATCH "https://weblate.example.com/api/components/project/component/" \
-H "Authorization: Token YOUR_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"commit_pending": 15, "commit_pending_age": 60, "push_on_commit": true}'
Verification steps:
- In Weblate, make a test translation change in any language.
- Wait 60 minutes (or make 14 more changes).
- Check the remote repository:
git log --oneline -5 origin/i18n/mainshould show a commit from "Weblate <[contact removed]>". - Confirm CI ran once for that batch, not per change.
Risks: If the push fails (expired deploy key, network blip), the commit stays in Weblate's local clone until the push succeeds. You should monitor the Repository maintenance page for "push failed" warnings.
Trade-off: noise vs. latency vs. conflict risk
| Setting combo | CI load | Visibility delay | Conflict risk |
|---|---|---|---|
| Low commit_pending + push_on_commit | High | Seconds | High (many small pushes) |
| High commit_pending + push_on_commit | Low | Hours | Medium (larger divergent pushes) |
| Any commit_pending + no push_on_commit | Zero (until manual push) | Manual | Low (you control push timing) |
There's no universal best. A solo maintainer with a quiet repo can push on every commit. A team with protected branches and heavy CI should batch and push. A project using GitHub Actions with paths-filter to skip CI for translation-only paths can tolerate more frequent pushes.
Version differences you'll actually hit
Weblate has changed how commit_pending is modeled across major releases. Some releases use a single integer for the change count; others split it into a count and an age threshold. REST API field names changed accordingly. If you're scripting configuration, check /api/about/ for the version and adjust your payload.
Defaults for push_on_commit have also shifted between releases. Never assume — always verify in the UI or API for your deployed version.
How to verify your setup today
- Open the component's Version control settings page. Note the exact values shown.
- Make a single test translation. Wait for the configured age threshold.
- Run
git fetch origin && git log --oneline -1 origin/from a local clone. Confirm the commit author is Weblate and the timestamp matches. - If using
push_on_commit: false, manually trigger a push from Weblate's Repository maintenance → Push button and verify the commit appears upstream.
That's it. No invented metrics, no guesswork — just the actual behavior of your deployed instance.