> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Text snippets

> Text snippets are the central location where all texts that the shop displays in various places are maintained.

export const confRechte = "Einstellungen -> Benutzer -> Benutzer bearbeiten";

export const confTextbausteine = "Templates und Content -> Textbausteine und Übersetzungen";

A text snippet consists of a name and a text. The template only references the name, not the text itself. That way the text is changed in one place and the change takes effect everywhere the snippet is used. Typical examples are buttons, notes, error messages, and legal texts.

| Name                                   | Text (German)              | Text (English)          |
| -------------------------------------- | -------------------------- | ----------------------- |
| `shop.basket.addButton`                | In den Warenkorb           | Add to cart             |
| `shop.checkout.shippingNote`           | Versandkostenfrei ab 50 €. | Free shipping from €50. |
| `ws.error.addressValidation.minLength` | Die Eingabe ist zu kurz.   | The entry is too short. |

The name is the technical identifier under which the template or a configuration requests the text. The text is what the customer reads in the shop.

## Languages are the foundation

Text snippets always exist in the context of a language. Three points belong together here:

* **Each language is created once in the shop** – as an independent object in the configuration, not in the text snippet service.
* **Each subshop has exactly one language.** Which text a customer sees depends on which subshop they call: the subshop determines the language, the language determines the text.
* **A text snippet has its own version per language.** The name is always the same, the text differs.

As long as no language has been created and assigned to a subshop, there are also no texts the shop could output. How languages are created, assigned, and chained together is described under [Creating and assigning languages](#creating-and-assigning-languages).

## Text maintenance

The texts are maintained in the Admin Interface under the service {confTextbausteine}, reachable at:

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://www.<ihr-shop>.de/admin/text
```

Permissions are granted per service, under {confRechte}. For text snippets there are five of them:

| Permission  | Allows                                                          |
| ----------- | --------------------------------------------------------------- |
| **View**    | Open the overview, view texts, search and filter, export.       |
| **Edit**    | Change existing texts.                                          |
| **Create**  | Create new text snippets and duplicate existing ones.           |
| **Delete**  | Remove text snippets or individual languages of a text snippet. |
| **Publish** | Make changes take effect in the shop.                           |
| **All**     | All of the above permissions are granted.                       |

An import, for example, requires the Create and Edit permissions.

<Note>
  The permissions always apply to the entire service, not to individual languages. Anyone who may read texts sees all languages; anyone who may edit can change all languages. Restricting access to individual languages – for example for external translators – is currently not possible. For a translation job, the [export of a single language](#import-and-export) is therefore the suitable way.
</Note>

## The overview

<Frame caption="Screenshot as of 25.08.2026">
  <img src="https://mintcdn.com/websaleag-44ee7ea6/M6zjhcPtj-Ax_Bwr/images/textblocks-lang3.png?fit=max&auto=format&n=M6zjhcPtj-Ax_Bwr&q=85&s=22b67b535ce6f3b270d0b0bcb8d57a5e" alt="Textblocks Lang3" width="2207" height="1321" data-path="images/textblocks-lang3.png" />
</Frame>

The service shows a table in which each row corresponds to a text snippet and each additional column to a language. Up to three languages can be compared side by side and edited directly in the table. You choose which languages appear as columns; they can be reordered via drag & drop.

The left language column is the focus language. It is highlighted, and the availability filters always refer to it – not to the other visible columns. Dragging a language all the way to the left makes it the focus language.

### The availability status

The availability status indicates the state of a text snippet in a specific language. There are three variants, color-coded in the cells:

* **green = maintained** – a text is present.
* **yellow = empty** – an entry exists for this language, but without content.
* **red = missing** – no entry exists yet for this language.

This makes it easy to see at a glance where gaps still exist in a language.

### Searching and filtering

Since many text snippets across multiple languages accumulate over time, the overview can be searched and filtered.

* **Search** – by name and text.
* **Availability** – exactly the three colors from the table. You can therefore specifically display all snippets that are empty or missing in the focus language and work through the gaps of a language. Several states can be combined; everything that has one of the selected states is then displayed.
* **Type** – system text snippets or custom text snippets.
* **Usage** – whether the snippet is referenced in a template. The reference can be restricted to a single subshop, because the templates of different subshops can use different snippets. How this state comes about is described under [Effect in the shop](#effect-in-the-shop).
* **Namespace** – a tree view over the dot levels of the names. The tree is not predefined but arises from the names that actually exist in the shop: `shop.checkout.button.label` produces the levels `shop`, `shop.checkout`, and `shop.checkout.button`. How useful this filter is therefore depends on how consistently the names are chosen. If you name new snippets according to a fixed scheme – for example with a prefix per shop area – you can later filter out a specific area.

## System and custom text snippets

### System text snippets

System text snippets are **generated automatically** by the shop. They arise from configuration fields that are predefined by the system and not editable – usually error texts. Their name begins with `ws.error.`

Such fields exist not only in the [actions](/en/konfiguration/actions-fehlertexte-e-mails), but also in other areas such as checkout, user accounts, and external data sources. The field in the configuration does not carry the error text itself, only the name of the text snippet; the text is maintained exclusively here in the text snippet service.

<Note>
  With shop updates, new system text snippets are added continuously as soon as new configuration areas or extensions are delivered. These are usually delivered with German text, and only in the main language of the respective subshop. You have to enter texts for further languages yourself.

  After an update, it is therefore worth taking a look at the availability filter: setting the focus language to the language in question and filtering by *missing* shows exactly the newly added gaps.
</Note>

What you may and may not do with system text snippets:

* **The text is freely changeable** – in every language, without restriction. You can therefore fully adapt the phrasing of an error message to your own wording.
* **The name is locked.** System text snippets can neither be renamed nor deleted – not even per language. The shop references this name at a fixed place; without it, there would be no text there.

### Custom text snippets

When a shop is provisioned, a large set of custom, freely changeable text snippets is already delivered. The templates themselves contain **no** texts – all texts reside in text snippets. This makes it possible to adapt the entire wording of a shop via this service without touching a template.

Beyond that, you can create any number of custom text snippets, for example for individual notes or content that is only needed in this shop. These can be fully created, edited, renamed, and deleted again.

**Allowed characters in the name:** letters `a–z` and `A–Z`, digits `0–9`, dot `.`, and underscore `_`. Spaces, hyphens, umlauts, and all other special characters are not allowed. The dot is more than a separator: it forms the levels of the namespace filter (see [Searching and filtering](#searching-and-filtering)). The prefix `ws.` is reserved for system text snippets and cannot be assigned.

<Warning>
  Creating a text snippet is not enough for it to appear in the shop. The name must additionally be inserted at the desired place in the template or in a configuration. The reverse applies to deleting: first remove the snippet from the template and configuration and delete it afterwards – otherwise the output location references a name that no longer exists.
</Warning>

How a text snippet is embedded in the template is described under [Template engine](/en/frontend/die-basics/template-engine).

### Text snippets in configurations

Not only templates reference text snippets, but configurations do as well. Wherever a configuration contains a text that appears in the frontend, the name of a text snippet can be used instead of a fixed value. This is not limited to system text snippets – you can also reference custom snippets there.

The advantage: the same configuration can be used in several language versions of a shop without duplicating it per language. Details under [Using text snippets in configurations](/en/konfiguration#verwendung-von-textbausteinen-in-konfigurationen).

A text snippet referenced by a configuration cannot be deleted as long as the reference exists. Remove the reference in the configuration first.

### Cleaning up unused snippets

The **unused** filter shows text snippets that no longer appear in any template. This is more than cosmetics.

After a relaunch, a template rebuild, or larger changes to the shop, snippets that nobody needs anymore regularly remain behind. As long as they are in the list, they reappear with every new language – and get translated along with everything else. If you filter for unused snippets and clean them up once before adding a new subshop or a new language, you save exactly this effort. Only the texts that the shop actually outputs are then displayed and translated.

<Note>
  Before deleting, check whether the state is up to date: usage is determined during template compilation (see [Effect in the shop](#effect-in-the-shop)). Immediately after a template change without republishing, the display is not yet up to date.
</Note>

## Creating and assigning languages

<Note>
  This section concerns shop administration. It is not needed for day-to-day editorial work – it explains how the languages that the text snippet service works with come into being.
</Note>

Languages are not maintained in the text snippet service but in the shop configuration. Three steps are involved, and their order also explains how inheritance works.

### 1. Create the language

Each language is its own configuration node under `general.language` with a name and an ISO code. Reference and parameters: [`general` – General shop settings](/en/konfiguration/general-allgemeine-shopeinstellungen).

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://<shop-domain>/admin/config/general.language
```

As soon as a language exists, it appears in the text snippet service as a selectable column – initially red everywhere, because no text has been maintained yet.

### 2. Assign the language to a subshop

A subshop gets **exactly one** language. It is entered in two places, and both must name the same language:

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
https://<shop-domain>/admin/config/general.subshopView
https://<shop-domain>/admin/config/general.subshop
```

<Warning>
  The most commonly overlooked point is that there are two places. If only one is changed, the error remains inconspicuous, because the shop continues to display texts – just the wrong ones. An Austrian subshop, for example, then still appears with German texts even though Austrian language variants are maintained.

  In this case, first check whether `general.subshopView` and `general.subshop` name the same language.
</Warning>

### 3. Set fallback languages

<Frame caption="Screenshot as of 25.08.2026">
  <img src="https://mintcdn.com/websaleag-44ee7ea6/M6zjhcPtj-Ax_Bwr/images/textblocks-languagechains.png?fit=max&auto=format&n=M6zjhcPtj-Ax_Bwr&q=85&s=d346b46bfdd4b5e65912b1939e8352f2" alt="Textblocks Languagechains" width="2207" height="1325" data-path="images/textblocks-languagechains.png" />
</Frame>

So that not every language variant has to be fully maintained, a language can have an ordered list of **fallback languages**. If a text is missing or empty in the actual language, the next language in this list takes effect.

What matters is where this list is entered: **it belongs to the language, not to the subshop.** The subshop only brings along its one language; which fallback languages stand behind it is decided by the language itself. This results in the effective order:

```text theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
Language of the subshop  →  its fallback language 1  →  its fallback language 2  →  …
```

An example for an Austrian subshop:

1. The subshop gets the language **German (AT)**.
2. For the language **German (AT)**, **German** is entered as the fallback language.
3. Result: if a text is missing in German (AT), the shop displays the German text.

The chain therefore always points from the **more specific** language to the more general one.

<Warning>
  Anyone coming from WEBSALE V8s often expects the opposite pattern: a master language `DEU` with the variants `AT` and `CH` entered as fallback languages. That does not lead to the goal and is the most common reason why a subshop shows the texts of the base language despite a maintained language variant.

  The correct way is the reverse: `AT` and `CH` are separate languages, and for **each** of them, `DEU` is entered as the fallback language.
</Warning>

Chains can be multi-stage – for example a very specific variant that first falls back to a more general one and only then to the base language. The rule here: **the chain is not inherited further.** Each language carries its complete list itself. For `de-at-b2b` to fall through `de-at` down to `de`, both must be entered for `de-at-b2b`. It is not enough for `de-at` to reference `de` itself.

The effect for editors: it is not necessary to maintain every text in every language variant. It is enough to fully maintain the base language. More specific variants automatically take over its contents as long as they have no text of their own. Only when a variant needs a deviating text do you enter it there deliberately – it then overrides the inherited version only for this language.

<Warning>
  For the output in the shop, **empty** and **missing** behave the same: both trigger the fallback to the fallback language. A deliberately empty stored text therefore does not suppress the output – as long as any language in the chain contains a text, that text is displayed. To actually display nothing at a given place, the text must be empty or missing in all languages of the chain.

  The difference between the two states is therefore mainly an indicator for editors: it shows whether a language has already been worked on.
</Warning>

## Effect in the shop

Two points are central for understanding, because they easily lead to confusion:

<Steps>
  <Step title="The text snippet must be embedded in the template">
    A text snippet is only displayed if it is embedded in the template at the appropriate place. Creating or changing a text snippet alone is not enough. The respective shop page must also actually reference this text snippet at the corresponding place. If you change an already embedded text snippet, the change takes effect immediately. A completely new text snippet only appears in the frontend once it has additionally been inserted into the respective template.
  </Step>

  <Step title="Changes only become visible after publishing">
    Until publication, changes remain in the editing state without customers seeing them. During publishing, the templates are recompiled with the most recently changed texts – the same process that also recalculates the usage state.
  </Step>
</Steps>

For the **usage** filter, this means: it reflects the state of the last compilation, not the current template content. After changes to templates, it is only up to date after republishing. A pure text change without a template change does not change the usage.

## Import and export

<Frame caption="Screenshot as of 25.08.2026">
  <img src="https://mintcdn.com/websaleag-44ee7ea6/M6zjhcPtj-Ax_Bwr/images/textblocks-export.png?fit=max&auto=format&n=M6zjhcPtj-Ax_Bwr&q=85&s=f28a32b6dc2488a3f4d46ea156453093" alt="Textblocks Export" width="2207" height="1325" data-path="images/textblocks-export.png" />
</Frame>

Larger amounts of text snippets can be exported and imported again, for example to have them translated externally or to apply changes in bulk. This can be limited to a single language, so that for example only the French texts are exported, translated externally, and then imported again.

The export takes the currently set search and the set filters into account. Both processes run in the background and are accompanied by a progress indicator. Imported texts also only become visible in the shop after publication.

System text snippets can be updated via import, but not newly created – the `ws.` prefix remains reserved for the system.

<Note>
  Before larger or destructive actions, an export is recommended as a backup, because an export can be re-imported unchanged.
</Note>

## Guide

* [Template engine](/en/frontend/die-basics/template-engine) – how text snippets are embedded in the template.
* [actions – error texts & emails](/en/konfiguration/actions-fehlertexte-e-mails) – how the system error texts (`ws.error.*`) are structured.
* [Overview – Configuration](/en/konfiguration#verwendung-von-textbausteinen-in-konfigurationen) – how configurations reference text snippets instead of containing fixed texts.
* [`general` – General shop settings](/en/konfiguration/general-allgemeine-shopeinstellungen) – reference for `general.language`, `general.subshop`, and `general.subshopView`.
* [Configuration deep links](/en/admin-interface/konfigurations-deeplinks) – direct links to the configuration nodes.
* [API reference text snippets](/en/schnittstellen/admin-interface-api/api-referenz-textbausteine) – endpoints, filters, and import/export interface.


## Related topics

- [Template engine](/en/frontend/die-basics/template-engine.md)
- [API reference text snippets](/en/schnittstellen/admin-interface-api/api-referenz-textbausteine.md)
- [actions - Error texts & emails](/en/konfiguration/actions-fehlertexte-e-mails.md)
- [Overview - Configuration](/en/konfiguration.md)
- [Changelog](/en/changelog.md)
