Texte übersetzen: Sprachdateien und der t-Filter

Wie die Sprachdateien aufgebaut sind, wie sie ausgewählt werden — und warum derzeit immer die Standardsprache gewinnt.

Für Entwickler

Voraussetzungen

  • Recht: website:write

Sprachdateien liegen unter `locales/<code>.json`. Ein `.default` im Dateinamen wird beim Einlesen abgeschnitten: aus `de.default.json` wird der Schlüssel `de`.

Der Inhalt ist verschachteltes JSON, etwa `{"header":{"reserve":"Reservieren","menu":"Menü"},"footer":{"closed":"Geschlossen"}}`. Im Template greifen Sie darauf mit einem Punktpfad zu: `{{ "header.reserve" | t }}`.

Fehlt ein Eintrag, gibt der Filter den Schlüssel selbst zurück. Eine fehlende Übersetzung sieht man also im Ergebnis und muss nicht danach suchen.

Der ganze Inhalt der aktiven Sprachdatei steht zusätzlich als Objekt `locales` bereit, die Kennung der aktiven Sprache als `locale`.

Eine Einschränkung, die man kennen muss: Die Sprache wird beim Rendern derzeit NICHT aus der Anfrage übernommen. Gerendert wird immer mit der Standardsprache des Themes. Eine zweite Sprachdatei wird zwar eingelesen und lässt sich pflegen, kommt auf der veröffentlichten Seite aber nicht zum Zug.

Codebeispiele

locales/de.default.json
AusschnittJSON
{  "kopf": {    "reservieren": "Tisch reservieren",    "menue_oeffnen": "Menü öffnen"  },  "karte": {    "leer": "Die Karte wird gerade überarbeitet."  },  "fuss": {    "oeffnungszeiten": "Öffnungszeiten",    "geschlossen": "Geschlossen"  }}
Ausschnitt: läuft nicht für sich allein — er gehört an die passende Stelle einer bestehenden Vorlage.Das `.default` im Dateinamen wird beim Einlesen abgeschnitten — der Sprachschlüssel heisst also `de`. Beliebig tief verschachteln geht; im Template greifen Sie mit einem Punktpfad darauf zu.
locales/en.json
AusschnittJSON
{  "kopf": {    "reservieren": "Book a table",    "menue_oeffnen": "Open menu"  },  "karte": {    "leer": "Our menu is being updated."  },  "fuss": {    "oeffnungszeiten": "Opening hours",    "geschlossen": "Closed"  }}
Ausschnitt: läuft nicht für sich allein — er gehört an die passende Stelle einer bestehenden Vorlage.Die SCHLÜSSEL bleiben in jeder Sprachdatei gleich, nur die Werte wechseln. Beachten Sie die Einschränkung aus dem Fliesstext: gerendert wird derzeit immer mit der Standardsprache des Themes.
Texte im Template nachschlagen
Liquid
<h2>{{ 'fuss.oeffnungszeiten' | t }}</h2><ul>{%- for tag in restaurant.opening_hours %}  <li>{{ tag.label }}: {% if tag.closed %}{{ 'fuss.geschlossen' | t }}{% else %}{{ tag.times }}{% endif %}</li>{%- endfor %}</ul>
Der Punktpfad `fuss.geschlossen` zeigt auf `{"fuss":{"geschlossen":…}}`. Zeigt er auf ein OBJEKT statt auf einen Text, erscheint `[object Object]` — dann ist der Pfad zu kurz.
snippets/uebersetzt.liquid
Liquid
[{{ 'fuss.geschlossen' | t }}]
Ein absichtlich winziges Teilstück — es dient dem nächsten Beispiel als Versuchsaufbau.
Die Falle: der t-Filter wirkt nicht in einem render-Teilstück
Liquid
mit render: {% render 'uebersetzt' %}
mit include: {% include 'uebersetzt' %}
DAS ist der Stolperstein bei Übersetzungen. `{% render %}` gibt dem Teilstück einen LEEREN Geltungsbereich — damit ist auch `locales` weg, und der Filter gibt nur noch den Schlüssel zurück. Entweder Sie übersetzen im aufrufenden Template und reichen den fertigen Text als Parameter herein, oder Sie nehmen `{% include %}`.
Die Sprachdatei direkt als Objekt
Liquid
Aktive Sprache: {{ locale }}
Über den Filter: {{ 'fuss.geschlossen' | t }}
Direkt aus dem Objekt: {{ locales.fuss.geschlossen }}
Der ganze Inhalt der aktiven Sprachdatei steht als `locales` bereit. Der Unterschied: ein fehlender Eintrag ergibt hier eine LEERE Ausgabe, während der Filter den Schlüssel zeigt. Für die Fehlersuche ist der Filter deshalb der bessere Weg.

Wo im Dashboard

/restaurant/[slug]/website/themes/[id]/code

Im Dashboard öffnen