Overrides & the Lock File
Two small JSON files at your project root are what let lingosync run incrementally instead of re-translating your entire master file every single time. Both should be committed to git.
.translations-lock.json
A snapshot of every key in your master file, as of the last successful sync — specifically, a SHA-256 hash of each key's value, not the value itself. On the next sync, lingosync compares the master's current state against this snapshot to classify every key:
| Key is... | Classified as |
|---|---|
| in the master, not in the lock | added |
| in both, but the value's hash differs | changed |
| in both, with the same hash | unchanged |
| in the lock, no longer in the master | removed |
Only changed keys (plus any key genuinely missing from a target locale file) get sent to the translation provider. added is tracked for the summary report, but — deliberately — doesn't by itself force a retranslation. That distinction matters more than it might look: if it did, adopting lingosync in a project that already has hand-written translations would overwrite all of them on the very first run, since every key in an empty lock file counts as "added". lingosync checks the target file directly instead, so existing translations always survive the first sync.
.translations-overrides.json
Where lingosync override writes. It maps locale -> key -> value for every pinned translation:
{
"version": 1,
"overrides": {
"es": {
"greeting.title": "Hola"
}
}
}During sync, any key with an entry here for the current locale skips translation entirely and uses this value — permanently, until you change it with another override call. This is the mechanism for: a translation the automatic provider got slightly wrong, region-specific phrasing you want to control by hand, or content you never want auto-translated at all.
Orphaned overrides
If the key an override points to gets deleted from the master, sync still removes that key from every locale file as normal — but the override entry itself is left in place. This is intentional: deleting a key could have been a mistake, and the override is still meaningful information until a human decides to clean it up. Nothing in sync does that automatically.
Run lingosync prune-overrides when you want to remove overrides whose key no longer exists anywhere. It's always a separate, explicit step.