---
title: Email Template Translations | Shopware Community Hub
description: >-
  Learn how to translate existing Shopware email templates, update translations
  via the Admin API, and understand how sales channel context, headers,
  footers,…
canonical_url: 'https://hub.shopware.com/learn/unit/email-template-translations'
---

# Email Template Translations

<LearningObjectives>

- Understand how email template types, templates, languages, and sales channel context interact.
- Distinguish email template translations from sales-channel-specific header and footer assignment.
- Understand how Flow Builder or custom sending logic controls which mail template is sent.
- Update email template translations via the Admin API using the correct template and language IDs.
- Safely use Twig variables and snippets within localized email templates.
- Test, preview, and validate email output across languages and sales channel contexts.
  
</LearningObjectives>

# Email Template Translations

Emails are a core touchpoint for customers. In multi-language shops, mail template content must be localized per language, and the rendered email can also depend on the sales channel context in which the mail is sent.

This learning unit focuses on translating and managing **existing email templates** via the administration, the Admin API, and Twig. It also clarifies where sales channel settings belong: mail header and footer records can be assigned to sales channels, while the actual mail template is usually selected by the mail-sending configuration, for example in the Flow Builder.

## The Mental Model

Before you edit an email template, separate the parts that often get mixed together.

The **email template type** defines the business situation of the email, for example an order confirmation. It also defines which data can be available in the mail payload.

The **email template** contains the content that the customer sees: sender name, subject, HTML content, and plain text content. These fields are translated per language.

The **sales channel context** is different. It can provide data such as the current sales channel, but it does not mean that the email template content is assigned directly to a sales channel.

The **header and footer** are reusable parts around the email content. This is where sales-channel-specific branding usually belongs.

Keep this separation in mind: Translate the email content in the template, use header and footer records for reusable branding, and let the sending logic decide which template is sent.

## Overview: Creating Email Templates in Plugins

In Shopware, email templates can be added or extended by plugins when custom business emails are required. This is typically done during plugin installation using database migrations or repository writes.

At a conceptual level, creating email templates in a plugin has three main building blocks:

- **Mail Template Type**: Defines the business context of an email (e.g., order confirmation or password reset) and determines which variables are available in the template payload.
- **Mail Template**: Contains the actual email content, including sender name, subject, HTML content, and plain text content. These fields are translatable and stored per language.
- **Mail Header and Footer**: Contains reusable header and footer content. Header and footer records can be translated and assigned to sales channels.
- **Flow Builder or mail-sending logic**: Selects which mail template is sent for a specific event or action.

Translated fields such as `subject`, `contentHtml`, and `contentPlain` follow Shopware's standard translation mechanism. Each language version is stored separately and resolved based on the active language context.

Plugins can also extend available data for email templates by adding custom variables to the mail payload, which can be used in Twig templates.

### Sales Channel Assignment

In the administration email template settings, direct sales channel assignment mainly applies to **mail headers and footers**. A header and footer record can be assigned to one or more sales channels and is then added around the email content for that sales channel.

![Administration Email Templates Headers and Footers](assets/images/administration-email-templates-headers-and-footers.jpg)

![Administration Email Template Default Email Footer](assets/images/administration-email-templates-headers-and-footers-default-email-footer.jpg)

The mail template itself is selected when the email is sent, for example by the Flow Builder's **Send email** action or by custom mail-sending logic. If you need different templates per sales channel, configure the sending logic accordingly, for example with separate flow branches or conditions.

Inside the template content, `salesChannel` can be available as a Twig variable. This gives you access to sales channel data in the rendered email, but it is not the same as assigning the template itself to a sales channel.

## Common Confusion: Sales Channel and Email Templates

A sales channel is not assigned directly to the email template content in the email template editor.

Use these places instead:

- Use **Header & Footer** records when reusable branding should differ per sales channel.
- Use the **Flow Builder** or custom sending logic when different sales channels should send different templates.
- Use the `salesChannel` variable inside Twig when you only need to render sales channel data in the email content.

## Managing Translations in the Administration

1. Go to Settings → Content → Email templates.
2. Select the template type, then the specific template.
3. Switch the language dropdown.
4. Translate subject, HTML content, and plain text content.
5. If recurring branding should differ by sales channel, create or edit a Header & Footer record and assign it to the relevant sales channel.
6. If a different template should be sent for a specific sales channel, configure that in the mail-sending logic, such as the Flow Builder.

**Recommendations:**

- Keep placeholders/variables identical across languages.
- Prefer snippets for recurring static UI phrases (e.g., greetings).
- Use preview with a test payload to verify real output.

## Managing Translations via Admin API

Update an email template translation (subject + contents). Replace IDs and language IDs with your values.

```bash
curl -X PATCH "https://your-shop.com/api/mail-template/TEMPLATE_ID" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "translations": {
      "LANGUAGE_ID_EN_GB": {
        "subject": "Your order {{ order.orderNumber }} is confirmed",
        "contentHtml": "<p>Hello {{ customer.firstName }},</p><p>Thanks for your order {{ order.orderNumber }}.</p>",
        "contentPlain": "Hello {{ customer.firstName }},\nThanks for your order {{ order.orderNumber }}."
      },
      "LANGUAGE_ID_DE_DE": {
        "subject": "Ihre Bestellung {{ order.orderNumber }} ist bestätigt",
        "contentHtml": "<p>Hallo {{ customer.firstName }},</p><p>vielen Dank für Ihre Bestellung {{ order.orderNumber }}.</p>",
        "contentPlain": "Hallo {{ customer.firstName }},\nvielen Dank für Ihre Bestellung {{ order.orderNumber }}."
      }
    }
  }'
```

**Notes:**

- Use language IDs as keys inside `translations`.
- Variables come from the template type payload (e.g., `order`, `customer`, `salesChannel`).
- Sales-channel-specific headers and footers are managed via header/footer records and the sales channel's `mailHeaderFooter` assignment.
- If different sales channels should use different mail templates, configure the flow or custom mail-sending logic that selects the template.

### Example With Postman

Let's look at a simple Postman example. In this example, we update the translated content of a custom order confirmation email template.

The example uses a custom template for demo purposes, but the same principle applies to existing templates: you need the mail template ID, the language IDs, and an Admin API access token.

![Administration Email Template Content Empty](assets/images/administration-email-template-content-empty.jpg)

In this example, the mail template ID is:

```text
019e838a26657318b58181e75e3c017f
```

You also need the IDs of the languages you want to update. In a local development shop, you can get them from the database:

```sql
SELECT name, REPLACE(BIN_TO_UUID(id), '-','') AS UUID FROM language;
```

<Callout title="Reminder" type="info">

Shopware stores UUIDs as binary values in the database. `BIN_TO_UUID(id)` converts the binary value into a readable UUID, and `REPLACE(..., '-', '')` removes the hyphens.

For the Admin API payload in this example, use the UUID without hyphens, for example `019e3f3d4c617028a81fc303b7c1a3fc`. A UUID with hyphens, such as `019e3f3d-4c61-7028-a81f-c303b7c1a3fc`, is easier to read but not the format used in the request body here.

</Callout>

The result can look like this:

```txt
|   | Name    | (UUID)                           |
|---|---------|----------------------------------|
| 1 | Deutsch | 019e3f3d4c617028a81fc303b7c1a3fc |
| 2 | English | 2fbb5fe2e29a4d70aa5854ce7ce3e20b |
```

You can also find the language IDs in the administration under `Settings → Languages`. Open a language and copy the ID from the browser URL.

![Administration: Settings Languages](assets/images/administration-settings-languages.jpg)

![Administration: Settings Languages: Language UUID EN](assets/images/administration-settings-languages-en.jpg)

![Administration: Settings Languages: Language UUID DE](assets/images/administration-settings-languages-de.jpg)

In this example, the language IDs are:

- English: `2fbb5fe2e29a4d70aa5854ce7ce3e20b`
- German: `019e3f3d4c617028a81fc303b7c1a3fc`

Before you send the PATCH request, create an integration in your local shop under `Settings → Integrations`. You need the access key ID and secret access key to request a bearer token through `/api/oauth/token`.

In Postman, the token request can look like this:

![Reminder: Admin API: POST Request Bearer Token](assets/images/admin-api-bearer-token-reminder.jpg)

After you have the bearer token, send the PATCH request to the mail template endpoint. In Postman, the request can look like this:

![Admin API: PATCH Request Email Template Content](assets/images/admin-api-patch-request-email-template-content.jpg)

<Callout type="info">

In the Authorization tab, set the type to **Bearer Token** and add the token you generated before.

</Callout>

Click **Send**. If the request is successful, Shopware returns an empty response body.

When you go back to the email template in the administration, you can see the updated content.

Before:

![Administration: Custom Email Template Before API Update](assets/images/administration-email-template-content-empty.jpg)

After:

![Administration: Custom Email Template Updated via API EN](assets/images/administration-email-template-content-set-via-request-en.jpg)

![Administration: Custom Email Template Updated via API DE](assets/images/administration-email-template-content-set-via-request-de.jpg)

## Using Twig Variables Safely

Email templates use Twig to render dynamic values. The available variables depend on the email template type and on the data passed when the email is sent.

Use variables for dynamic data, such as an order number or a customer name. Use snippets for recurring static text, such as greetings or shared footer text.

```twig
{# Subject #}
{% trans_default_domain 'messages' %}
{{ "mail.order.subject"|trans({"%orderNumber%": order.orderNumber}) }}

{# HTML content #}
<p>{{ "mail.greeting"|trans({"%firstName%": customer.firstName}) }}</p>
<p>{{ "mail.order.body"|trans({"%orderNumber%": order.orderNumber}) }}</p>

{# Plain content #}
{{ "mail.footer"|trans }}
```

When you translate email content, keep the placeholders stable across languages. The wording can change, but variables such as `order.orderNumber` or snippet placeholders such as `%orderNumber%` must still be present where the email needs them.

## Before You Ship a Mail Template Change

Before you consider an email template update done, test it like a customer would receive it.

First, check the content for every active language that should receive the email. If a language is not translated yet, make sure the fallback behavior is intentional.

Then preview or send the email with realistic test data. Check the subject, HTML content, and plain text content. Also check whether the assigned header and footer are correct for the relevant sales channel.

Finally, verify the small details that often break during translation work:

- Variables and placeholders are still present in every language.
- Subjects are short and contain important identifiers, such as the order number.
- Shared phrases are handled through snippets where reuse makes sense.
- HTML stays simple enough for common email clients.
- Template changes and translation changes are reviewed together.

This gives you a safer workflow: translate the content, verify the rendered result, and only then treat the email as ready.

## Summary

In this learning unit, you have learned:

- How to translate and manage existing email templates.
- How email template types, templates, languages, sales channel context, and header/footer records relate to each other.
- Where and how email translations are managed in the administration.
- How to update translations programmatically via the Admin API.
- Why sales channel assignment in the email template settings mainly applies to Header & Footer records.
- How Flow Builder or custom mail-sending logic controls which template is sent.
- Why `salesChannel` in Twig is context data and not a template assignment.
- How to safely use Twig variables and snippets in localized email templates.
- How to test, preview, and validate email outputs across languages and sales channel contexts.

With this knowledge, you can maintain localized email content more safely and choose the right place for language, sales channel, and template-specific changes.
