---
title: "Skeletons and hashes"
description: "Learn how diglot turns a segment into the text a translator sees and the hash that identifies it."
canonical_url: "https://diglot.sh/guide/concepts/skeletons-and-hashes"
---
# Skeletons and hashes

> Learn how diglot turns a segment into the text a translator sees and the hash that identifies it.

A translator should see the words of a sentence and nothing else. Links, inline code, components and HTML are not theirs to touch, and they should not cause a new translation when they change. diglot achieves both by replacing those spans with placeholders, which produces a *skeleton*, and by hashing the skeleton.

## The skeleton

Take this paragraph:

```md
Nuxt is powered by [Nitro](https://nitro.build), and `useFetch` is built in.
```

Its skeleton is:

```text
Nuxt is powered by {0}Nitro{/0}, and {1} is built in.
```

`{n}` stands for a protected span such as inline code, an image, a component, inline HTML, a binding or a hard break. `{n}...{/n}` wraps the text of a link, so the link text is translated while the URL stays hidden. If the text of a link has no letters, or looks like a URL or an email address, the whole link becomes a single `{n}` placeholder. Bold, italic and strikethrough keep their markers (`**`, `*`, `~~`), so a translation can place emphasis around the equivalent words.

Placeholder ids are numbered in order of appearance. The translator may move them to fit the grammar of the target language, but every placeholder of the source has to come back, and paired ones must stay paired and nested.

Before the skeleton is built, whitespace runs collapse into single spaces and the text is trimmed. Markdown punctuation in prose is escaped with a backslash. As a result, re-wrapping source lines or editing a protected span doesn't change the skeleton.

## The hash

A segment's hash is the SHA-256 of its skeleton, truncated to 16 hexadecimal characters. The paragraph above hashes to `87ecf1244d975205`, and every document in every source that contains the same skeleton shares that hash. This is why identical text is translated once.

Three consequences follow from hashing the skeleton and not the source text:

- Changing the URL of a link, the contents of an inline code span or the attributes of a component doesn't change the hash, so the existing translation still applies. The segment's `sourceHash`, a hash of the full text, does change, which is how diglot can tell that a protected span moved without a new translation.
- Plain and markdown segments hash apart, even when their skeletons are equal, so each translation is validated under one set of rules.
- A *context salt* can be mixed into the hash. A short string such as `Open` may need different translations in different places, and a [policy](https://diglot.sh/core/policy-and-config) can return a salt for such segments so that each context gets its own hash and its own record.

## What a translation may contain

A translation is also written as a skeleton, and it is accepted only if it follows the translation grammar:

- Text, with special characters escaped.
- Emphasis markers, balanced and correctly nested.
- Every placeholder of its source, each in the right form.

Anything that would parse as other markdown is rejected, including inline code, links, raw HTML, components, bindings and bare URLs. Plain segments must stay on one line and may not add markup that the source doesn't have. The [validation reference](https://diglot.sh/core/validation) lists each rule and the issue code it produces.

When a translation is applied, the placeholders are filled from the current source, never from the record. A link in a translated page therefore always points where the source points today.

## Next steps

- [Translation records](https://diglot.sh/guide/concepts/translation-records) show where translations are stored under their hash.
- [Keeping in sync](https://diglot.sh/guide/concepts/keeping-in-sync) explains what happens to a hash when its source text changes.


## Sitemap

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