← Alle Themen · Tickets

In diesem Artikel 6 Kapitel
  1. Mehrsprachige Textbausteine
  2. Variablen
  3. Bedingungen
  4. Filter (Formatierung)
  5. Komplettes Beispiel (E-Mail-Template)
  6. Sicherheit (technisch)

Ticket-Textbausteine & E-Mail-Templates → Variablen & Bedingungen

Textbausteine (CRM → Ticket-Einstellungen → Textbausteine) und das E-Mail-Template pro Postfach (CRM → Postfächer → Bearbeiten → Reiter „E-Mail-Template") werden über Twig gerendert. Damit kannst du nicht nur Variablen einsetzen, sondern auch Bedingungen, Schleifen und Filter nutzen.

Mehrsprachige Textbausteine

Jeder Textbaustein hat einen Standard-Inhalt (Fallback) und beliebig viele Sprach-Varianten. Im Editor findest du oben eine Tab-Leiste: „Standard (Fallback)" + jeweils ein Tab pro hinzugefügter Sprache. Rechts kannst du per Dropdown eine neue Sprache anfügen oder bestehende entfernen.

Wie die Sprache gewählt wird

  1. Die KI-Sprach-Erkennung (oder die manuell im Ticket gesetzte Sprache) bestimmt die Ticket-Sprache (ISO-Code, z.B. fr)
  2. Beim Anwenden eines Textbausteins wird geprüft: existiert eine Variante mit language = fr?
  3. Ja: deren Betreff + Inhalt werden genutzt
  4. Nein: der Standard-Inhalt wird verwendet

Bei auftragsbasierten Events (Auftragsbestätigung etc.)

Wenn über ein Auftrags-Event (z.B. „Auftrag bezahlt" → Auftragsbestätigung) ein Ticket erzeugt wird, existiert noch keine erkannte Sprache. In diesem Fall leitet Scanalot die Sprache aus dem Lieferland (isoCode2) der Lieferadresse ab, z.B. FRfr, DE/AT/CHde, NLnl, ITit, ESes, GB/IE/USen. Bei nicht gemappten Ländern wird der Standard-Fallback verwendet. Die so ermittelte Sprache wird am neuen Ticket gespeichert, damit alle Folgeaktionen darauf aufbauen können.

Twig funktioniert in allen Sprach-Varianten

Variablen ({{ order.externalId }} …), Bedingungen ({% if %}) und Schleifen ({% for %}) werden in jeder Übersetzung gleich gerendert. Du schreibst die Twig-Logik also einfach pro Sprache dupliziert, die Daten bleiben dieselben, nur der umgebende Text ist übersetzt.

Anhänge pro Sprache

Statische Anhänge (PDFs, Bilder) kannst du pro Sprach-Tab hochladen:

  • Anhänge im Standard-Tab werden angehängt, wenn die Sprache des Tickets zu keinem Sprach-Tab passt (oder kein sprachspezifischer Anhang existiert)
  • Anhänge in einem Sprach-Tab werden ausschließlich bei Tickets in dieser Sprache verwendet

Beispiel: AGB.pdf (DE) im Sprach-Tab „DE", CGV.pdf (FR) im Sprach-Tab „FR", keine Standard-Anhänge. Ein Ticket auf Englisch bekommt dann keinen Anhang, ein Ticket in Deutsch AGB.pdf, ein Ticket in Französisch CGV.pdf.

Wo die Übersetzung greift

Überall, wo Textbausteine eingesetzt werden, manuelle Einfügung im Composer, Auto-Antwort per Automation, Auto-Responder des Postfachs, Auto-Close-Nachricht, Bulk-Versand über die Gruppenfunktion, Auftrags-Event-Trigger.


Variablen

Ticket

VariableBeschreibung
{{ ticket.id }}Interne Ticket-ID
{{ ticket.number }}Ticket-Nummer (T-YYYYMMDD-XXXXX)
{{ ticket.subject }}Betreff
{{ ticket.orderId }}Verknüpfte Auftrags-ID (0 wenn kein Auftrag verknüpft)
{{ ticket.mailboxId }}Postfach-ID

Kunde

VariableBeschreibung
{{ customer.name }}Name aus Absender-Adresse
{{ customer.email }}Absender-E-Mail

Benutzer (eingeloggter Scanalot-User)

VariableBeschreibung
{{ user.id }}Benutzer-ID
{{ user.name }}Name des Benutzers
{{ user.email }}E-Mail-Adresse des Benutzers
{{ user.position }}Position / Funktion (z.B. „Geschäftsführung"), wird unter Einstellungen → Benutzer gepflegt

Postfach (nur im E-Mail-Template)

VariableBeschreibung
{{ mailbox.id }}Postfach-ID
{{ mailbox.name }}Postfach-Name
{{ mailbox.email }}E-Mail-Adresse des Postfachs
{{ mailboxId }}Kurzform, gleiche ID wie mailbox.id

Die Postfach-IDs findest du in CRM → Postfächer in der ersten Spalte (Spalte „ID").

Auftrag (wenn verknüpft, sonst leere Werte)

VariableBeschreibung
{{ order.id }}Interne Scanalot-ID
{{ order.externalId }}Externe Auftragsnummer
{{ order.market }}Marktplatz (amazon, ebay, temu, etc.)
{{ order.type }}Typ: order, return, credit
{{ order.clientId }}Mandant-ID
{{ order.currency }}Währungscode (EUR, USD, …)
{{ order.totalGross }}Gesamtbetrag brutto
{{ order.totalNet }}Gesamtbetrag netto
{{ order.itemCount }}Summe aller Item-Mengen (ohne Versand)
{{ order.statusId }}Status-ID
{{ order.paymentType }}Zahlungsart
{{ order.createdAt }}Erstell-Timestamp (Unix)
{{ order.payedAt }}Zahlungs-Timestamp
{{ order.shippedAt }}Versand-Timestamp

Auftragspositionen order.items[]

{% for item in order.items %}
- {{ item.qty }}× {{ item.name }} ({{ item.sku }}) à {{ item.priceGross|number_format(2, ',', '.') }} {{ item.currency }}
{% endfor %}

Felder pro Item: id, type, sku, name, qty, priceGross, priceNet, vat, currency, lineGross

Sendungen order.shipments[]

{% for s in order.shipments %}
Versand mit {{ s.carrier }}, Tracking: {{ s.trackingNr }}
{% endfor %}

Felder pro Sendung: id, carrier, trackingNr, returnTrackingNr, weightG, status, createdAt

Adressen

order.shippingAddress und order.invoiceAddress, beide mit diesen Feldern: firstname, lastname, company, street, houseNr, zip, city, country, email, telephone

Zeit & Datum

VariableBeschreibung
{{ hour }}Aktuelle Stunde (0–23)
{{ minute }}Aktuelle Minute (0–59)
{{ weekday }}Wochentag (1=Mo … 7=So)
{{ day }}Tag im Monat (1–31)
{{ month }}Monat (1–12)
{{ year }}Jahr (4-stellig)
{{ isWorkday }}1 = Mo–Fr, 0 = Sa/So

Nachricht (nur im E-Mail-Template)

VariableBeschreibung
{{ message }}Inhalt der Antwort (HTML), wird nicht escaped

Bedingungen

{% if hour < 11 %}Guten Morgen{% elseif hour < 18 %}guten Tag{% else %}guten Abend{% endif %}

{% if order.market == 'amazon' %}
Bei Amazon-Bestellungen gilt unser Standardversand.
{% elseif order.market == 'temu' %}
Bei Temu-Bestellungen senden wir über die Temu-Plattform.
{% endif %}

{% if mailboxId == 5 %}
Rücksendeadresse DE: Berliner Str. 1, 10115 Berlin
{% elseif mailboxId == 7 %}
Rücksendeadresse IT: Via Roma 1, 00100 Roma
{% endif %}

{% if order.totalGross > 100 %}
Als Dankeschön für Ihre Bestellung über 100 € erhalten Sie einen 5%-Gutschein.
{% endif %}

{% if order.shippingAddress.country == 'CH' %}
Hinweis: Schweiz-spezifische Zoll-Info
{% endif %}

Filter (Formatierung)

FilterBeispielErgebnis
`upper``{{ customer.nameupper }}`MUSTERMANN
`lower``{{ customer.emaillower }}`max@test.de
`capitalize``{{ 'hallo welt'capitalize }}`Hallo welt
`title``{{ 'hallo welt'title }}`Hallo Welt
`trim`entfernt Leerzeichen
`striptags`entfernt HTML-Tags
`default('—')`Fallback bei leerem Wert
`date('d.m.Y')``{{ order.createdAtdate('d.m.Y') }}`20.04.2026
`number_format(2, ',', '.')``{{ order.totalGrossnumber_format(2, ',', '.') }}`22,18
`nl2br`Zeilenumbrüche → <br>
`length`Array/String-Länge
`slice(0, 5)`erste 5 Elemente/Zeichen
`replace({'alt': 'neu'})`String ersetzen

Komplettes Beispiel (E-Mail-Template)

<p>{% if hour < 11 %}Guten Morgen{% elseif hour < 18 %}guten Tag{% else %}guten Abend{% endif %} {{ customer.name|default('') }},</p>

{{ message }}

{% if order.id %}
<p><strong>Ihre Bestellung:</strong></p>
<ul>
{% for item in order.items %}
  {% if item.type == 'item' %}
  <li>{{ item.qty }}× {{ item.name }} — {{ item.lineGross|number_format(2, ',', '.') }} {{ item.currency }}</li>
  {% endif %}
{% endfor %}
</ul>
<p>Gesamt: <strong>{{ order.totalGross|number_format(2, ',', '.') }} {{ order.currency }}</strong></p>
{% endif %}

<p>Mit freundlichen Grüßen
{% if mailboxId == 5 %}
aus Deutschland,<br>
{{ agent.name }}<br>
Berliner Str. 1, 10115 Berlin
{% elseif mailboxId == 7 %}
dall'Italia,<br>
{{ agent.name }}<br>
Via Roma 1, 00100 Roma
{% else %}
<br>{{ agent.name }}
{% endif %}
</p>

Sicherheit (technisch)

Das Rendering läuft in einer Twig-Sandbox, folgende Dinge sind bewusst blockiert:

  • Keine PHP-Funktionen aufrufbar (kein file_get_contents, exec, system, etc.)
  • Kein Dateisystem-Zugriff (kein include, extends, source)
  • Keine Objekt-Methoden ({{ user.delete() }} wirft Fehler)
  • Keine Properties (nur Arrays im Kontext)
  • Keine URL-Requests möglich

Bei Syntaxfehlern im Template greift ein Fallback: einfaches {{variable}}-Replace ohne Bedingungen. Damit bricht der Ticket-Versand nie ab, nur die erweiterte Logik fehlt dann.