Docs / Concepts
The translation cache
What verbatra.cache.json reuses between runs, how a fingerprint scopes each entry to its config, and why a cache problem never fails a run.
The translation cache, verbatra.cache.json, is a local translation memory keyed by content: it
remembers the translation of a piece of source text, whichever key holds it, so the same text is
never paid for twice. The lock file answers "is this key up to date?"; the
cache answers "have we translated this text before?".
What it reuses
Before a key goes to the provider, verbatra looks up the hash of its current source entry: the text plus its description, meaning, plural flag and placeholders. A hit is free. Because the lookup is by content, reuse survives what the lock file cannot see:
- A renamed key. Move
home.titletolanding.titleand its translation is reused. - Duplicate content. Two keys with the same source text and context share one translation.
A reused value is not trusted blindly. It passes the same integrity gate against the current source as a fresh translation, and one that no longer fits is discarded and translated anew. Cache hits are reported per locale, apart from the keys translated this run.
A value a reviewer rejected is never reused for that key:
the provenance file keeps a hash of the refused text, and a run skips any hit that matches it. The
one gap is a provenance file the run cannot read (one from a newer verbatra, or a corrupt one under
humanEdits: "overwrite"); the run then knows no rejection.
The fingerprint
Every entry is scoped to the context it was produced in: a fingerprint over the provider, the
model, the tone, the glossary terms of that locale, and the provider's
localeMap when it has entries. Change any of
them and earlier entries stop matching, so a new tone or an edited glossary retranslates instead of
serving a stale result. The glossary part is the terms verbatra would send to the provider, after any sensitiveData setting that withholds or redacts a term, whether or not the configured provider uses glossary terms (DeepL, Google Cloud Translation and LibreTranslate ignore them), so an edited term still retranslates. A term's caseSensitive flag is not part of it. Each locale has its own fingerprint, so editing only the German translation
of a glossary term leaves the French entries matching.
The format is not part of the fingerprint; the integrity gate on every hit catches a value that no
longer fits. With provider none, every entry goes into one human-only bucket that tone and
glossary do not affect.
Fuzzy reuse
An exact hit needs the source text to hash to the same value as before, so editing one character
makes it a miss. fuzzyCache is an opt-in fallback for that case:
when a key misses, verbatra scores its source against the other entries of the same locale and
fingerprint, and reuses the closest one at or above threshold. The score is one minus the
character edit distance divided by the length of the longer string, so 1 is identical.
The threshold is not a safety setting
Character distance is not meaning. Dropping a "not", turning "cannot" into "can" or swapping one
brand name for another are small edits that score above 0.9 and reverse what the sentence says.
The threshold decides how much provider spend you avoid, not how safe a reuse is. Safety comes from
rules that do not depend on the number:
- It is off unless you turn it on.
- Every fuzzy reuse is flagged for review with
FUZZY_, on every run, whatever it scored. If nobody works the review queue, leave it off.CACHE_ REUSE - Changed numerals refuse the reuse. If the numerals in the two sources differ in count, value
or order, the entry is not a candidate. This covers every Unicode numeric character (
m²tom³,½to¼), but not numbers written as words. - A reuse does not settle the key. The lock keeps the key's old baseline, so it stays changed:
every later run offers it again at no provider cost, and
checkkeeps reporting it, until a real translation lands. - An unchanged source text never reaches the fuzzy layer. Editing only a description or a plural flag sends the key to the provider as usual.
What a fuzzy reuse still is not
A fuzzy reuse is a translation of text that is no longer the source, so it is never presented as an exact hit:
- It passes the integrity gate like any other candidate; a near match whose placeholders no longer fit is refused, and the key goes to the provider.
- It is reported apart from exact hits, as
fuzzy-reused, with the key, the score and the earlier source text; the SDK carries the same onLocaleSummary.fuzzyHits. - It is never written back into the cache, so a later run cannot mistake it for an exact hit.
Scoring stays inside one fingerprint and is bounded: at most 256 candidates per key, and source text
longer than 2,000 characters is skipped. With provider none, a fuzzy match is never applied.
The file
verbatra.cache.json is a local, regenerable file next to your lock file. Keep it out of version
control: it is a cost optimization, not a shared baseline. verbatra init gitignores it, and
translate, watch, import, tmx import and pseudo add the entry to an existing .gitignore
that lacks it and say so on stderr.
The cache never fails a run. A missing, corrupt or oversized file becomes an empty cache and is rebuilt. A file from a newer verbatra is also treated as empty for the run, but left on disk untouched, with a notice. To start over, delete the file. For fuzzy scoring the file stores each source string beside its translations, so it grows roughly to the size of your source text.
Moving a memory between tools
verbatra tmx imports a TMX file from another translation tool into the cache and
exports the cache as TMX. Imported units are stored under the current fingerprint, so they stop
matching when the provider, model, tone, the glossary terms verbatra would send or localeMap changes, like everything else. One
caveat to "delete it and it rebuilds": an imported memory is only as recoverable as the TMX file it
came from, so keep that file.
Bypassing it
--no-cache on translate or watch (cache: false in
the SDK) makes exactly the provider calls a run without a cache would, fuzzy reuse included, and
leaves the file untouched. To keep exact reuse and drop only the fuzzy fallback, leave fuzzyCache
out of the config. A dry run never writes the cache, and reads it only with provider none, so
that plan matches a live run.
Limitation
Plural forms synthesized by generatePlurals are not cached, so they always come from the provider.
Related
fuzzyCache: the config key and its range.verbatra tmx: import and export the memory as TMX.- How a run works: where the cache lookup sits in the pipeline.
- Estimate cost before a run: what the cache saves before you spend.