The hardest translation bug to catch is the one where nothing is missing. Every key exists, every placeholder matches, every file parses. But three weeks ago you changed "Cancel anytime" to "Cancel before renewal" in the source, and four languages still say the old thing. Legally meaningful copy, silently outdated.
No stateless check can find this. A linter sees a key with a value in both files and calls it healthy. Detecting staleness requires memory: you have to know what the source said the last time the translation changed.
The obvious approaches and why they fail
- ·Git blame: works only if locale files live in one repo with clean history, breaks on squash merges, formatting commits, and files exported from a TMS.
- ·TMS workflow states: accurate inside the TMS, but it only knows about strings that went through it. The hotfix someone committed directly is invisible.
- ·Timestamps in the files: nobody maintains them, and they say when a line changed, not whether the meaning did.
Scan-history hashing
Polylens does it with two hashes and a table. On every scan, each source value is hashed, and each translation value is hashed. The scan history then answers the question directly: if the source hash for a key changed at some scan, and the translation hash has not changed in any scan since, the translation is stale.
scan 41: source("billing.hint") = h(A) de = h(X)
scan 42: source("billing.hint") = h(B) de = h(X) <- source moved
scan 43: source("billing.hint") = h(B) de = h(X) <- de still h(X): staleNo git access, no TMS integration, no annotations in the files. The detector needs nothing but its own scan history, which means it works the same whether your translations come from an agency, a pull request, or a machine.
Severity and the score
Stale strings are warnings, not errors: the UI is not broken, it is lying, which is usually worse but never urgent in the same way a raw key is. In the health score they subtract less than a missing key and more than a whitespace drift. The drift trend is where they show up best: a language that quietly accumulates stale strings bleeds a point a week, and the chart makes the bleed visible long before a user does.
The practical consequence: rewording source copy stops being a silent risk. Change the English, push, and every language that still carries the old meaning is flagged on the next scan, listed per key, ready to hand to whoever translates.
Get a health score for your locale files in under a minute. Free for one project.