Reference / SDK
Key history
Read how one key's translation changed from commit to commit, with the author, where the value came from and a word-level difference.
Git history of one key
keyHistory
Lists the commits in which one key's value changed in one target locale, newest first, each with a word-level difference from the previous value. Read-only; it takes a locale and a key, never a path, and runs git log and git cat-file through the injectable execFile.
function keyHistory(
input: KeyHistoryInput,
deps?: KeyHistoryDeps,
): Promise<KeyHistoryResult>;Prop
Type
Returns: KeyHistoryResult
Throws: UNKNOWN_, UNKNOWN_, LOCALE_, LOCALE_
Each revision carries commit, authorDate, author (the name after .mailmap, never the email), subject, value, origin, sourceChanged and diff. Control and bidirectional formatting characters are stripped from author and subject, recognised keys in them are replaced by [REDACTED] (a former custom key in an unrecognised shape can remain) before they are cut to 200 and 500 characters. A text that one revision gives away as a key (an api_ before a bare UUID, say) is also replaced wherever else it appears in the answer, and valueRedacted is set on every value that changed this way. diff lists { kind, text } segments with kind equal, added or removed: placeholders and tags stay whole, a change of whitespace shows as a change, and a difference too large to align becomes one removed and one added run. origin comes from the provenance file as committed with the revision: a stored origin, unrecorded, or external when its record describes another value, and absent when that file could not be read or parsed, is above 4 MiB, or the time ran out first. sourceChanged compares the content hash of the key's current source entry (its text, description, meaning, plural flag and placeholders) with the hash the committed lock-file recorded for the key in that locale: true when they differ, false when they match, and "unknown" when the lock-file, its entry for the key or the current source entry is missing, could not be read or parsed, is above its limit, or the time ran out first. origin is separate: it compares the revision's value with the provenance record, and is absent, not "unknown", when that file cannot be used. Restoring a value whose source entry changed makes it count as up to date.
Every value and both sides of every diff pass redact. A value that held an API key comes back with [REDACTED] in its place and valueRedacted: true: it is not the stored text, so do not offer it for restore. A key that is no longer configured cannot be recognised and is returned as written.
The commits come from git log --first-parent on the locale file (and the .stringsdict file for apple-strings), so a change a merge brought in is listed on the merge commit. Each file is read with git cat-file blob and parsed by the built-in adapter, and a commit is listed only if the key's value differs from the commit right before it in the file's history, which must have been read. A commit that removes the key is not listed. Up to LOCALE_ commits are examined (LOCALE_ by default), four files are read at a time, and after KEY_ (30000 milliseconds) no further commit is examined and no commit file read starts (the file on disk is still read); the git log call, a size listing and a read already running keep their own 10 second limit. truncated is true when anything the call examined was skipped, unreadable, above a size limit, past a budget or stopped by the deadline, and truncatedBy says why, listing every cause that applies from KEY_: commit-limit (more commits exist than limit examines), shallow-clone, unreadable-revision, file-too-large, byte-budget, deadline, source-unreadable, records-unreadable (a lock or provenance file) and scrub-cap (more than 256 distinct keys, one key longer than 4096 characters, or keys adding up to more than 65,536 UTF-16 code units turned up; the pass cannot cover every text, so every non-empty value, diff segment, subject and author name becomes [REDACTED], empty text stays empty, and valueRedacted is set on every revision). truncatedBy is empty exactly when truncated is false, and the file on disk is reported only by workingTreeUnreadable. A commit is listed only if the commit before it was read, so a commit whose older neighbour could not be read is not claimed as the key's change.
Sizes come from git before anything is parsed, so the same repository gets the same byte-limit and budget decisions on every machine; a git call that times out, the 30 second deadline and the provider keys in the environment (which decide what is scrubbed) can still change an answer. A locale file above 512 KiB for yaml and the XML formats (xliff, android-xml, resx, apple-strings) or above 4 MiB for the other formats is skipped unparsed, and the two files of an apple-strings commit count as their sum. One call reads at most 16 MiB of locale files for yaml and the XML formats and 128 MiB for the others: older commits past that are not examined. A lock file or provenance file above 4 MiB is not read, and one call reads at most 128 MiB of them together: past that, older revisions have no origin and sourceChanged is "unknown". The source file is read up to the same size as the locale files. Parsing yields to the event loop between files. A commit skipped for its size, that cannot be read or parsed, whose log line did not parse, or whose value is longer than KEY_ (4096) characters, counts in unreadableRevisions and is never returned in part; a commit past a budget is not examined and does not count. key is at most KEY_ (1024) characters and never reaches git. workingTree carries the value on disk, with its diff, when it differs from HEAD. When the value on disk cannot be compared with HEAD (the file does not parse, as during a merge conflict, is a symbolic link or is above its limit, its value is too long, the copy at HEAD could not be read, or time ran out) the revisions are still listed and workingTreeUnreadable is true.
Renames are not followed, so history before a rename is not listed; edits that were never committed are not seen, and a key renamed in the source looks new. The git safeguards are those of localeGitStatus, and the result is { available: false, reason } with a reason from LOCALE_, custom-adapter for a custom: format included.
Run history
runHistory
Reads .verbatra-local/run-history.jsonl, where every translate, watch, retranslateEntry and retranslateEntries run that left a trace adds one record. It writes nothing, calls no provider and throws nothing.
function runHistory(
input?: RunHistoryInput,
deps?: RunHistoryDeps,
): Promise<RunHistoryResult>;Prop
Type
Returns: RunHistoryResult
records come newest first, at most limit of them (RUN_ is 50, RUN_ is 200; any other value is clamped). Each record holds the time, the trigger (translate or retranslate), the provider and model, token usage, the cost, and per locale the counts of translated keys, cache hits, fuzzy hits, generated plural forms, pruned keys, integrity refusals and provider failures. A record never holds a key name or a text. A dry run is not recorded, and neither is a run that left no trace, such as a watch cycle with nothing to do; a failed or refused run is recorded. entries counts the entries a retranslate record attempted, a failed provider call included, and a batch of retranslations is one record. The file keeps the newest 1,000.
cost is frozen when the run ends, from the rates the config held then. pricing priced adds currency, asOf and amount; no-rate-on-file, rate-unit-mismatch and no-usage (keys were sent and the provider reported no tokens) carry no amount, which means unknown, not free; not-billed (verbatra does not price this provider: a self-hosted openai-compatible or LibreTranslate server, or none; a hosted endpoint may still bill you) carries neither an amount nor a basis, and carries USAGE_ when part of its usage went unreported. basis (one of RUN_) usage is the provider's token count. source-characters is an estimate for DeepL and Google Cloud Translation, which report no usage: the source characters of the keys sent, cache hits left out, refused keys counted, failed keys not, with caveats naming what it leaves out. A usage figure carrying the caveat USAGE_ is a lower bound, priced or not: a locale sent keys and reported no tokens, so the amount and the token count cover only what was reported. A locale that reported for some of its sub-batches and not others cannot be told apart and shows no mark.
After the run, one check over the locales it touched sets each locale's coverage (missing, stale, upToDate). A locale without it was not measured, and coverageUnavailable says the pass failed.
unreadableRecords counts lines left out because they could not be read, and the next recorded run rewrites the file without them. unavailable (one of RUN_: unreadable or too-large above 8 MiB) says the whole file could not be read, so an empty list is then not proof that nothing ran. An unreadable file is left as it is and no record is added to it, and a line that is not valid UTF-8 counts as one unreadable record.