---
title: "Translation records"
description: "Learn what a translation record contains and why one file per locale and hash is stored in git."
canonical_url: "https://diglot.sh/guide/concepts/translation-records"
---
# Translation records

> Learn what a translation record contains and why one file per locale and hash is stored in git.

A record is one translation of one source segment into one locale. It is a small JSON file at `<locale>/segments/<hh>/<hash>.json`, where `<hh>` is the first two characters of the hash.

Because records are plain files in git, a translation has a history, an author and a review like any other change. A pull request shows exactly which sentences were translated, edited or rejected.

## Fields

A record looks like this. The values are an illustration of the shape and not output from a real run.

```json [fr/segments/87/87ecf1244d975205.json]
{
  "hash": "87ecf1244d975205",
  "source": "Nuxt is powered by {0}Nitro{/0}, and {1} is built in.",
  "text": "Nuxt est propulsé par {0}Nitro{/0}, et {1} est intégré.",
  "origin": "mt",
  "review": "none",
  "derived": "fresh",
  "mt": {
    "model": "anthropic/claude-sonnet-5.5",
    "promptVersion": "1",
    "candidate": "Nuxt est propulsé par {0}Nitro{/0}, et {1} est intégré."
  },
  "updatedAt": "2026-01-01T00:00:00.000Z"
}
```

<table>
<thead>
  <tr>
    <th>
      Field
    </th>
    
    <th>
      Meaning
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        hash
      </code>
    </td>
    
    <td>
      The identity of the source <a href="https://diglot.sh/guide/concepts/skeletons-and-hashes">
        skeleton
      </a>
      
      . It must match the file name.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        source
      </code>
    </td>
    
    <td>
      The source skeleton, so a reviewer can read the record on its own.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        text
      </code>
    </td>
    
    <td>
      The translated skeleton.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        origin
      </code>
    </td>
    
    <td>
      Who produced the current text: <code>
        mt
      </code>
      
       for a machine, <code>
        tm
      </code>
      
       for a translation memory, <code>
        human
      </code>
      
       for a person.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        review
      </code>
    </td>
    
    <td>
      What a person has done to it: <code>
        none
      </code>
      
      , <code>
        edited
      </code>
      
      , <code>
        verified
      </code>
      
       or <code>
        rejected
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        derived
      </code>
    </td>
    
    <td>
      How it relates to <code>
        prev
      </code>
      
      : <code>
        fresh
      </code>
      
       has no predecessor, <code>
        carry
      </code>
      
       copied its text, <code>
        update
      </code>
      
       was derived from it.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        prev
      </code>
    </td>
    
    <td>
      The hash of the record this one evolved from. Required when <code>
        derived
      </code>
      
       is <code>
        carry
      </code>
      
       or <code>
        update
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        salt
      </code>
    </td>
    
    <td>
      The context salt of the source segment, when its hash is salted.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        mt
      </code>
    </td>
    
    <td>
      The model, the prompt version and the unedited machine output (<code>
        candidate
      </code>
      
      ).
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        by
      </code>
    </td>
    
    <td>
      The GitHub login of the last editor.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        verifiedBy
      </code>
    </td>
    
    <td>
      <code>
        { by, at }
      </code>
      
       for the person who verified the text. Required when <code>
        review
      </code>
      
       is <code>
        verified
      </code>
      
      .
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        rejectedBy
      </code>
    </td>
    
    <td>
      <code>
        { by, at }
      </code>
      
       for the person who rejected it. Required when <code>
        review
      </code>
      
       is <code>
        rejected
      </code>
      
      , and allowed only then.
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        updatedAt
      </code>
    </td>
    
    <td>
      An ISO 8601 timestamp.
    </td>
  </tr>
</tbody>
</table>

Records are validated whenever they are read or written. An unknown key, a hash that is not 16 hexadecimal characters or a missing required field is an error, and `diglot validate` reports it.

## Why the machine candidate is kept

When a model writes a record, it stores its unedited output in `mt.candidate`. If a reviewer then edits `text`, the difference between the two shows how much of the draft needed correcting. `editRatio` in [`@diglot/core`](https://diglot.sh/core/records) computes that share.

## Records are not segments

A record exists only for hashes that have been translated. A hash with no record is untranslated, and a record whose hash no source uses any more is *unused*. Unused records stay in git, but bundles leave them out by default.

## Next steps

- [Review and status](https://diglot.sh/guide/concepts/review-and-status) explains how these fields combine into what readers see.
- [Review translations](https://diglot.sh/guide/how-to/review-translations) shows how to edit, verify and reject a record.


## Sitemap

See the full [sitemap](https://diglot.sh/sitemap.md) for all pages.
