Ein praktischer Leitfaden zum Schreiben von CEL-Ausdrücken im CMS.
Ein praktischer Leitfaden zum Schreiben von CEL-Ausdrücken im CMS.
CEL (Common Expression Language) ist eine leichtgewichtige Skriptsprache, die in unser CMS integriert ist. Damit können Sie dynamische Ausdrücke schreiben, die Daten aus Dokumenten abrufen, URL-Parameter lesen und Werte direkt berechnen.
Folgendes geschieht beim Ausführen eines CEL-Skripts:
Ihr Skript Die Engine Ergebnis
| | |
v v v
documents.get("article", "intro") --> Ruft Daten aus der Datenbank ab --> { headline: "Welcome", body: "..." }
.headline --> Extrahiert das Feld --> "Welcome"
Stellen Sie sich CEL als schreibgeschützte Abfragesprache vor. Sie kann nichts in der Datenbank ändern – sie liest lediglich Daten und gibt ein berechnetes Ergebnis zurück. Dadurch kann sie überall im CMS sicher verwendet werden.
Jeder CEL-Ausdruck kann auf drei Dinge zugreifen:
| Objekt | Was es ist | Beispiel |
|---|---|---|
documents | Ruft ein beliebiges Dokument aus dem CMS ab | documents.get("country", "us") |
meta | Informationen zur aktuellen Anfrage (Lokalisierung, URL-Parameter) | meta.locale, meta.params.slug |
schema | Felddefinitionen des aktuellen Dokuments | schema.fields |
docBeim Schreiben von CEL-Ausdrücken innerhalb eines Dokumenteditors können Sie über das Objekt doc auf die Feldwerte des aktuellen Dokuments zugreifen. Dies ermöglicht berechnete Felder und Referenzen zwischen Feldern.
// Auf das Preisfeld des aktuellen Dokuments zugreifen
doc.price
// Gesamtsumme aus Feldern des aktuellen Dokuments berechnen
doc.price * doc.quantity
// Bedingung basierend auf dem Status des aktuellen Dokuments
doc.status == "published" ? doc.title : "Draft: " + doc.title
Das Objekt doc enthält alle Feldwerte des bearbeiteten Dokuments. Dies ist nützlich für:
doc.price * doc.quantity)Die leistungsfähigste Funktion von CEL ist das Abrufen von Dokumenten aus beliebigen Bereichen Ihres CMS.
Syntax: documents.get(schemaName, identifier)
Angenommen, Sie haben ein article-Dokument mit dem Bezeichner "welcome-post":
// Im CMS gespeichert als: article / welcome-post
{
"headline": "Welcome to Our Platform",
"author": "Sarah Chen",
"body": "We're excited to announce...",
"tags": ["announcement", "news"]
}
Das gesamte Dokument abrufen:
documents.get("article", "welcome-post")
Gibt zurück:
{
"headline": "Welcome to Our Platform",
"author": "Sarah Chen",
"body": "We're excited to announce...",
"tags": ["announcement", "news"]
}
Nur die Überschrift abrufen:
documents.get("article", "welcome-post").headline
Gibt zurück: "Welcome to Our Platform"
Den Autor abrufen:
documents.get("article", "welcome-post").author
Gibt zurück: "Sarah Chen"
Wenn Ihre Seite dynamische Routen enthält (z. B. /articles/[slug]), können Sie mit meta.params den URL-Parameter auslesen und das passende Dokument abrufen.
Wenn jemand /articles/welcome-post besucht:
documents.get("article", meta.params.slug).headline
Gibt zurück: "Welcome to Our Platform"
So erstellen Sie dynamische Seiten – dasselbe CEL-Skript funktioniert für jeden Artikel und verwendet einfach den Slug aus der URL.
Syntax: documents.find(schemaName) oder documents.find(schemaName, filter)
// Alle Länder abrufen
documents.find("country")
Gibt zurück:
[
{ "code": "us", "name": "United States", "flag": "US" },
{ "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
{ "code": "gb", "name": "United Kingdom", "flag": "GB" }
]
// Länder mit einem Filter abrufen
documents.find("country", { "where": { "code": "us" } })
Gibt zurück:
[
{ "code": "us", "name": "United States", "flag": "US" }
]
CEL unterstützt das Abrufen übersetzter Dokumentinhalte auf zwei Arten: automatische übersetzungsbasierte Lokalisierung und eine explizite Übersetzungsabfrage.
Wenn meta.locale gesetzt ist (z. B. durch Routenparameter oder Benutzereinstellungen), führt documents.get() automatisch übersetzte Inhalte zusammen:
// Wenn meta.locale gleich "fr" ist, wird die französische Übersetzung mit dem Basisdokument zusammengeführt
documents.get("greeting", "welcome").headline
So funktioniert es:
meta.locale nicht "en" oder "en-US" ist, wird die Übersetzung in der Tabelle translations gesucht.{ ...baseContent, ...translatedContent }Das bedeutet: Übersetzte Felder überschreiben die Basisfelder, während nicht übersetzte Felder auf das Basisdokument zurückfallen.
Wenn Sie unabhängig von der aktuellen Lokalisierung eine bestimmte Übersetzung abrufen müssen:
Syntax: documents.translated(schemaName, identifier, locale)
// Immer die spanische Übersetzung abrufen
documents.translated("greeting", "welcome", "es").headline
// Übersetzung anhand eines URL-Parameters abrufen
documents.translated("product", meta.params.id, meta.params.lang).description
// Übersetzungen vergleichen
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title
Ihre Begrüßungsdokumente mit Übersetzungen:
// Basisdokument: greeting / welcome
{ "headline": "Welcome", "subheadline": "Welcome to our platform" }
// Übersetzung (Sprache: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }
// Übersetzung (Sprache: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }
CEL-Skripte:
// Mit meta.locale = "fr"
documents.get("greeting", "welcome").headline
// Gibt zurück: "Bienvenue"
// Explizite spanische Übersetzung
documents.translated("greeting", "welcome", "es").headline
// Gibt zurück: "Bienvenido"
// Fallback-Muster für fehlende Übersetzungen
documents.translated("greeting", "welcome", meta.params.lang) != null
? documents.translated("greeting", "welcome", meta.params.lang).headline
: documents.get("greeting", "welcome").headline
Sie haben einen hero-block, der eine Überschrift aus einem article-Dokument anzeigen soll.
Ihr Artikeldokument (Bezeichner: "homepage-hero"):
{
"headline": "Build Faster, Ship Smarter",
"subheadline": "The modern CMS for developers"
}
CEL-Skript im Titelfeld des Hero-Blocks:
documents.get("article", "homepage-hero").headline
Ergebnis: Der Hero zeigt "Build Faster, Ship Smarter" an.
Sie erstellen eine Seite unter /countries/[code] und möchten den vollständigen Ländernamen anzeigen.
Ihre Länderdokumente:
// country / us
{ "code": "us", "name": "United States", "flag": "US", "languages": ["en", "es"] }
// country / sa
{ "code": "sa", "name": "Saudi Arabia", "flag": "SA", "languages": ["ar", "en"] }
CEL-Skript:
documents.get("country", meta.params.code).name
Wenn jemand /countries/us besucht:
meta.params.code = "us""United States"Wenn jemand /countries/sa besucht:
meta.params.code = "sa""Saudi Arabia"Zeigen Sie je nach Lokalisierung des Benutzers unterschiedliche Überschriften an.
meta.locale == "ar-SA" ? "Welcome, everyone" : "Welcome"
Wenn die Lokalisierung "ar-SA" ist: Gibt "Welcome, everyone" zurück.
Bei jeder anderen Lokalisierung: Gibt "Welcome" zurück.
Ihr article enthält ein Feld countryCode, und Sie möchten den vollständigen Ländernamen abrufen.
Artikeldokument:
{ "headline": "News from the US", "countryCode": "us" }
CEL-Skript:
documents.get("country", documents.get("article", "us-news").countryCode).name
Was geschieht:
documents.get("article", "us-news") gibt { "headline": "News from the US", "countryCode": "us" } zurück..countryCode extrahiert "us".documents.get("country", "us") gibt { "code": "us", "name": "United States", ... } zurück..name extrahiert "United States".Ergebnis: "United States"
Wenn ein Dokument möglicherweise nicht existiert, können Sie einen Fallback angeben:
documents.get("article", meta.params.slug) != null
? documents.get("article", meta.params.slug).headline
: "Article Not Found"
Oder prüfen Sie, ob ein bestimmtes Feld existiert:
documents.get("article", "intro").author != null
? documents.get("article", "intro").author
: "Unknown Author"
Ihr Artikel enthält Tags, und Sie möchten prüfen, ob ein bestimmter Tag vorhanden ist:
"featured" in documents.get("article", "welcome-post").tags
Gibt zurück: true, wenn der Artikel den Tag "featured" enthält.
Ersten Tag abrufen:
documents.get("article", "welcome-post").tags[0]
Gibt zurück: "announcement" (der erste Tag).
Tags zählen:
size(documents.get("article", "welcome-post").tags)
Gibt zurück: 2 (Anzahl der Tags).
Parametrische Routen sind der Schlüssel zum Erstellen dynamischer, lokalisierter Seiten. Wenn Sie ein Routenmuster wie /{lang}/landingPage definieren, extrahiert das CMS die Parameter aus der URL und stellt sie über meta.params bereit.
Definition des Routenmusters:
Routen verwenden die Syntax :paramName oder {paramName}, um dynamische Segmente zu definieren:
| Muster | Beispiel-URL | Extrahierte Parameter |
|---|---|---|
/:lang/landingPage | /ko/landingPage | { lang: "ko" } |
/{country}/{lang}/products | /us/en/products | { country: "us", lang: "en" } |
/articles/:slug | /articles/welcome-post | { slug: "welcome-post" } |
Parameterbindungen: Jeder Routenparameter kann zur Validierung an ein Dokumentschema gebunden werden:
{
"pattern": "/{lang}/landingPage",
"param_bindings": {
"lang": "language"
}
}
Diese Bindung weist das CMS an:
lang aus der URL zu extrahieren.language zu validieren (es wird nach einem Dokument gesucht, bei dem content.code übereinstimmt).Routenkonfiguration:
/{lang}/landingPage/{lang}/landingPage{ "lang": "language" }Ihre Begrüßungsdokumente:
// greeting / ko
{ "code": "ko", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Get Started", "ctaUrl": "/ko/get-started" }
// greeting / en
{ "code": "en", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Get Started", "ctaUrl": "/en/get-started" }
// greeting / ja
{ "code": "ja", "headline": "Welcome", "subheadline": "Welcome to our platform", "ctaText": "Start", "ctaUrl": "/ja/get-started" }
CEL-Skript zum Abrufen lokalisierter Inhalte:
documents.get("greeting", meta.params.lang).headline
Auflösung:
| URL | meta.params.lang | Ergebnis |
|---|---|---|
/ko/landingPage | "ko" | "Welcome" |
/en/landingPage | "en" | "Welcome" |
/ja/landingPage | "ja" | "Welcome" |
Für Routen wie /{country}/{lang}/products:
Routenkonfiguration:
{
"pattern": "/{country}/{lang}/products",
"param_bindings": {
"country": "country",
"lang": "language"
}
}
CEL-Skripte:
// Ländernamen abrufen
documents.get("country", meta.params.country).name
// Lokalisierte Produktliste anhand des Landes abrufen
documents.find("product", { "where": { "country": meta.params.country } })
// Kombiniert: Länderspezifische Begrüßung in der Sprache des Benutzers anzeigen
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name
Validierungskaskade:
Das CMS validiert Parameter hierarchisch. Bei Routen nach dem Muster /{country}/{lang} geschieht Folgendes:
country wird anhand des Schemas country validiert.lang wird anhand des Schemas language validiert.lang im Array country.languages[] enthalten ist (hierarchische Validierung).meta.segments stellt den rohen URL-Pfad als Array bereit. Dies ist nützlich, wenn Sie ohne benannte Parameter positionsbezogen zugreifen müssen.
So funktioniert es:
| URL-Pfad | meta.segments |
|---|---|
/articles/tech/ai-news | ["articles", "tech", "ai-news"] |
/ko/landingPage | ["ko", "landingPage"] |
/us/en/products/featured | ["us", "en", "products", "featured"] |
/ | [] |
| Anwendungsfall | Beste Vorgehensweise |
|---|---|
| Benannte Parameter aus dem Routenmuster | meta.params.lang |
| Positionsbezogener Zugriff | meta.segments[0] |
| Pfadtiefe ermitteln | size(meta.segments) |
| Prüfen, ob der Pfad ein Segment enthält | "admin" in meta.segments |
// Erstes Segment abrufen (häufig der Sprachcode)
meta.segments[0]
// Pfadtiefe prüfen
size(meta.segments) > 2 ? "deep" : "shallow"
// Prüfen, ob wir uns im Administrationsbereich befinden
"admin" in meta.segments ? "admin mode" : "public mode"
// Fallback: Segment verwenden, wenn der Parameter nicht gebunden ist
has(meta.params.lang) ? meta.params.lang : meta.segments[0]
Das meta-Objekt enthält den gesamten Kontext der aktuellen Anfrage:
| Eigenschaft | Typ | Beschreibung | |
|---|---|---|---|
meta.locale | string | Aktueller Lokalisierungscode (z. B. "en-US", "ko-KR", "ar-SA") | |
meta.params | Record<string, string> | Aus dem URL-Muster extrahierte Routenparameter | |
meta.segments | string[] | In Segmente aufgeteilter URL-Pfad | |
meta.docId | `string \ | null` | UUID des aktuellen Dokuments (null bei neuen Dokumenten) |
meta.title | string | Titel des aktuellen Dokuments |
Der Lokalisierungscode folgt dem BCP-47-Format (Sprache-Region):
// Lokalisierung für von rechts nach links geschriebene Sprachen prüfen
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"
// Nur den Sprachteil abrufen
meta.locale.split("-")[0] // Nicht unterstützt – verwenden Sie stattdessen meta.params.lang
Routenparameter sind immer Zeichenketten. Das CMS validiert sie vor der Auswertung anhand gebundener Schemata:
// Benannten Parameter abrufen
meta.params.lang // "ko"
meta.params.country // "us"
meta.params.slug // "welcome-post"
// Prüfen, ob ein Parameter existiert
has(meta.params.category) // true/false
// In einem Dokumentabruf verwenden
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)
Rohe URL-Segmente als Array:
// Nach Index zugreifen (nullbasiert)
meta.segments[0] // Erstes Segment
meta.segments[1] // Zweites Segment
// Länge prüfen
size(meta.segments) // Anzahl der Segmente
// Zugehörigkeit prüfen
"products" in meta.segments // Enthält der Pfad "products"?
Die UUID des aktuellen Dokuments, nützlich für selbstreferenzierende Skripte:
// Nur beim Bearbeiten bestehender Dokumente verfügbar
meta.docId != null ? "editing" : "creating new"
// In bedingter Logik verwenden
meta.docId != null ? documents.get("article", meta.docId).status : "draft"
Der Titel des aktuellen Dokuments:
// Zur Anzeige verwenden
"Editing: " + meta.title
// Bedingung basierend auf dem Titel
meta.title.contains("Draft") ? "work in progress" : "published"
Für eine übersichtlichere Syntax, wenn das Schema bekannt ist, der Bezeichner jedoch dynamisch bleibt:
// Herkömmlicher Ansatz
documents.get("airports", meta.params.code).name
// Mit ref() – Schema getrennt vom dynamischen Bezeichner
documents.ref("airports").get(meta.params.code).name
Beide Varianten sind gleichwertig, aber mit ref() wird der dynamische Teil deutlicher.
documents.get("schema", "identifier") // Ein Dokument abrufen
documents.get("schema", "id").fieldName // Ein bestimmtes Feld abrufen
documents.find("schema") // Alle Dokumente abrufen
documents.find("schema", { "where": {...}}) // Gefilterte Abfrage
documents.ref("schema").get(identifier) // Verkettete Abfrage
documents.translated("schema", "id", "fr") // Mit expliziter Lokalisierung abrufen
meta.locale // "en-US", "ar-SA" usw.
meta.params.xyz // URL-Parameter mit dem Namen "xyz"
meta.segments // URL-Pfad als Array: ["articles", "intro"]
meta.segments[0] // Erstes Pfadsegment
meta.docId // ID des aktuellen Dokuments (oder null)
meta.title // Titel des aktuellen Dokuments
doc.fieldName // Feldwert des aktuellen Dokuments (im Editor-Kontext)
// Vergleich
== != < <= > >=
// Logik
&& || !
// Ternärer Operator (wenn-dann-sonst)
condition ? valueIfTrue : valueIfFalse
// Zugehörigkeit
"value" in listOrMap
size(list) // Elemente zählen
size(string) // Zeichenkettenlänge
"text".startsWith("te") // true
"text".endsWith("xt") // true
"text".contains("ex") // true
has(object.property) // Prüfen, ob eine Eigenschaft existiert
hasProperty(obj, "key") // Prüfen, ob ein Objekt einen Schlüssel besitzt (alternative Syntax)
Wenn etwas schiefgeht, wird eine der folgenden Meldungen angezeigt:
| Fehler | Bedeutung |
|---|---|
SYNTAX_ERROR | Tippfehler im Skript (fehlendes Anführungszeichen, ungültiger Operator) |
TYPE_ERROR | Es werden inkompatible Datentypen miteinander verwendet |
RUNTIME_ERROR | Das Skript wurde ausgeführt, ist aber auf ein Problem gestoßen (nicht definierte Variable) |
FETCH_LIMIT_EXCEEDED | Es werden zu viele Dokumente abgerufen (maximal 50) |
TIMEOUT | Das Skript hat zu lange gedauert (maximal 5 Sekunden) |
AST_DEPTH_EXCEEDED | Der Ausdruck ist zu tief verschachtelt (maximale Tiefe: 50) |
SCRIPT_TOO_LONG | Das Skript überschreitet das Limit von 5000 Zeichen |
Die CEL-Engine ist auf Erweiterbarkeit ausgelegt. Zu den geplanten zukünftigen Funktionen gehören:
// Zukunft: Externe Dienste über MCP aufrufen
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)
// Zukunft: KI-gestützte Inhaltsgenerierung
ai.summarize(documents.get("article", meta.params.id).body, 100)
ai.translate(meta.params.text, meta.params.targetLang)
ai.classify(meta.params.input, ["positive", "negative", "neutral"])
Diese Funktionen werden über das registrierte Funktionssystem hinzugefügt und bleiben mit bestehenden Skripten abwärtskompatibel.
documents. oder meta. ein, damit der Editor verfügbare Optionen anzeigt.documents.get("schema", "id") und fügen Sie anschließend .fieldName hinzu.!= null ? ... : ... einen Fallback hinzu.documents.get() oder documents.find() zählt zum Limit von 50 Abrufen.has(meta.params.category), bevor Sie auf den Parameter zugreifen.Dieser Abschnitt behandelt fortgeschrittene Muster zum Verknüpfen von Dokumenten und zum Aufbau relationaler Inhaltsstrukturen.
Die einfachste Form: Ein Dokument verweist anhand eines Bezeichners auf ein anderes.
// Artikel speichert die ID des Autors und ruft dessen Namen ab
documents.get("author", documents.get("article", "intro").authorId).name
Für eine übersichtlichere Syntax bei dynamischen Bezeichnern:
// Herkömmlicher Ansatz
documents.get("country", documents.get("airport", meta.params.code).countryCode).name
// Mit ref() – übersichtlicher, wenn das Schema bekannt, der Bezeichner aber dynamisch ist
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name
Erstellen Sie durch mehrere verkettete Abfragen tiefe Beziehungen:
// Flughafen → Land → Region → Kontinent
documents.get("continent",
documents.get("region",
documents.get("country",
documents.get("airport", meta.params.code).countryCode
).regionCode
).continentCode
).name
Kombinieren Sie Dokumentreferenzen mit Übersetzungen:
// Lokalisierter Ländername für einen Flughafen
documents.translated("country",
documents.get("airport", meta.params.code).countryCode,
meta.params.lang
).name
Das Dokument speichert eine ID, die auf ein anderes Dokument verweist.
// article / tech-news
{ "title": "Tech Update", "authorId": "author-123", "categoryId": "cat-tech" }
// Namen des Autors auflösen
documents.get("author", documents.get("article", meta.params.slug).authorId).name
// Kategorie mit Fallback auflösen
documents.get("article", meta.params.slug).categoryId != null
? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
: "Uncategorized"
Dokumente verweisen über semantische Codes statt über UUIDs aufeinander.
// airport / JFK
{ "code": "JFK", "name": "John F. Kennedy International", "countryCode": "us" }
// country / us
{ "code": "us", "name": "United States", "currencyCode": "usd" }
// currency / usd
{ "code": "usd", "symbol": "$", "name": "US Dollar" }
// Kette Flughafen → Land → Währung
documents.get("currency",
documents.get("country",
documents.get("airport", meta.params.code).countryCode
).currencyCode
).symbol
// Für JFK: Gibt "$" zurück
Verwenden Sie doc für berechnete Felder, die anhand der Werte des aktuellen Dokuments auf andere Dokumente verweisen.
// In einem Produktdokument Details der zugehörigen Kategorie abrufen
documents.get("category", doc.categoryId).description
// Berechnete Versandkosten anhand des Ursprungslandes des Produkts
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight
Wenn Dokumente aufeinander verweisen, achten Sie auf die Abruflimits.
// Autor des Artikels und anschließend weitere Artikel des Autors abrufen (Abrufanzahl beachten!)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })
Wenn ein Feld auf unterschiedliche Schemata verweisen kann:
// content-block / hero-1
{ "type": "hero", "sourceType": "article", "sourceId": "welcome-post" }
// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Dynamische Schemaabfrage anhand von sourceType
documents.get("content-block", "hero-1").sourceType == "article"
? documents.get("article", documents.get("content-block", "hero-1").sourceId).headline
: documents.get("product", documents.get("content-block", "hero-1").sourceId).name
Jeder Aufruf von documents.get(), documents.find() und documents.ref().get() wird für die Cache-Invalidierung verfolgt. Wenn sich ein referenziertes Dokument ändert, weiß das CMS, welche CEL-Ausdrücke neu ausgewertet werden müssen.
Verfolgte Abhängigkeiten umfassen:
schema:identifier – Abhängigkeit von einem bestimmten Dokumentschema:identifier – Wie get, über verkettete Syntaxschema:* – Abhängigkeit auf Schemaebene (jedes Dokument im Schema)// Schlecht: Ruft dasselbe Dokument zweimal ab
documents.get("author", documents.get("article", "intro").authorId).name + " - " +
documents.get("author", documents.get("article", "intro").authorId).bio
// Besser: Mit einer Bedingung nur einmal prüfen
documents.get("article", "intro").authorId != null
? documents.get("author", documents.get("article", "intro").authorId).name
: "Unknown Author"
Dieser Ablauf erstellt eine mehrsprachige Landingpage, die unter /{lang}/landingPage erreichbar ist.
Erstellen Sie im CMS-Administrationsbereich ein benutzerdefiniertes Schema namens greeting:
{
"name": "greeting",
"fields": [
{ "name": "code", "type": "string", "required": true },
{ "name": "headline", "type": "string", "required": true },
{ "name": "subheadline", "type": "string" },
{ "name": "ctaText", "type": "string" },
{ "name": "ctaUrl", "type": "string" }
]
}
Erstellen Sie für jede Sprache ein Dokument:
Dokument: greeting/ko
{
"code": "ko",
"headline": "Welcome",
"subheadline": "Welcome to our platform",
"ctaText": "Get Started",
"ctaUrl": "/ko/get-started"
}
Dokument: greeting/en
{
"code": "en",
"headline": "Welcome",
"subheadline": "Welcome to our platform",
"ctaText": "Get Started",
"ctaUrl": "/en/get-started"
}
Dokument: greeting/ja
{
"code": "ja",
"headline": "Welcome",
"subheadline": "Welcome to our platform",
"ctaText": "Start",
"ctaUrl": "/ja/get-started"
}
Erstellen Sie eine Seite mit der folgenden Konfiguration:
/{lang}/landingPagelang → die Komponente language zuordnen {
"lang": "language"
}
Fügen Sie der Route einen Hero-Block hinzu und verwenden Sie für jedes Feld die folgenden CEL-Skripte:
Feld „Überschrift“:
documents.get("greeting", meta.params.lang).headline
Feld „Unterüberschrift“:
documents.get("greeting", meta.params.lang).subheadline
Feld „CTA-Text“:
documents.get("greeting", meta.params.lang).ctaText
Feld „CTA-URL“:
documents.get("greeting", meta.params.lang).ctaUrl
Fügen Sie eine Catch-all-Route hinzu. ParametricRoutePage löst die Seite auf, extrahiert meta.params aus der URL, wertet Ihre CEL-Bindings serverseitig aus und rendert jeden Block über Ihre Registry – Sie müssen den meta-Kontext nicht selbst erstellen und den Client auf niedriger Ebene nicht direkt aufrufen.
// app/[...slug]/page.tsx
import ParametricRoutePage from 'cms-renderer/lib/renderer';
import { registry } from '@/lib/registry';
import { cmsConfig } from '@/lib/cms-config';
export const dynamic = 'force-static';
interface PageProps {
params: Promise<{ slug: string[] }>;
}
export default async function Page({ params }: PageProps) {
const { slug } = await params;
return (
<ParametricRoutePage
registry={registry}
apiKey={cmsConfig.apiKey}
websiteId={cmsConfig.websiteId}
cmsUrl={cmsConfig.cmsUrl}
params={Promise.resolve({ slug })}
/>
);
}
Besuchen Sie diese URLs, um lokalisierte Inhalte zu sehen:
| URL | Erwartete Überschrift |
|---|---|
/ko/landingPage | 환영 |
/en/landingPage | Welcome |
/ja/landingPage | いらっしゃいませ |
Wenn ein Benutzer /ko/landingPage besucht:
/{lang}/landingPage ab.meta.params.lang = "ko"language vorhanden ist.documents.get("greeting", meta.params.lang) werden zu koreanischen Inhalten aufgelöst.interface CelMeta {
/** Aktueller Lokalisierungscode (z. B. 'en-US') */
locale: string;
/** Aus der URL extrahierte Routenparameter */
params: Record<string, string>;
/** URL-Pfadsegmente */
segments: string[];
/** ID des aktuellen Dokuments (falls ein bestehendes Dokument bearbeitet wird) */
docId: string | null;
/** Titel des aktuellen Dokuments */
title: string;
}
Die Funktion extractParams verarbeitet URL-Pfade:
Muster: /{country}/{lang}/products
Pfad: /us/en/products
Algorithmus:
1. Beide normalisieren (abschließende Schrägstriche entfernen)
2. In Segmente aufteilen: ["us", "en", "products"] und ["{country}", "{lang}", "products"]
3. Segmentanzahl abgleichen (muss identisch sein)
4. Jedes Segmentpaar prüfen:
- Beginnt das Muster mit : oder {}, als Parameter extrahieren
- Andernfalls muss es exakt übereinstimmen
5. Rückgabe: { country: "us", lang: "en" }
// Einfache Bindung (verwendet das Feld "code" für die Suche)
{ "lang": "language" }
// Detaillierte Bindung (benutzerdefiniertes Slug-Feld)
{
"lang": {
"schemaName": "language",
"slugField": "code"
},
"slug": {
"schemaName": "article",
"slugField": "slug"
}
}
Beim Abruf über documents.get(schema, identifier) gilt folgende Reihenfolge:
id abgerufen.content.code wird geprüft.content.slug wird geprüft.title wird geprüft.Dadurch können Dokumente flexibel über jeden eindeutigen Bezeichner referenziert werden.