profound-logoProfound CMS
⌘K
Admin
Theme
DocsTutorialBlogPhilosophy
DocsTutorialBlogPhilosophy

Hybrid

Collection of Pages with ComponentsTypes of ComponentsSetup server sent events (SSE) content refetchInstall Profound CMS as a proxyCEL Scripting in Template BuilderProject ScaffoldingBibliotecă media

Fără interfață

Pornire rapidăSplit Screen JSON Component Builder with LLMComponent Zod Pull

API REST

Prezentare generală API RESTgetConnect your websitegetGET /routesgetGET /routegetGET /blocksgetObține blocuri cu cache CELgetGET /blocks/generatedgetGET /componentsgetGET /components/{name}getGET /dataset/{schema_name}getGET /content-changes (SSE)patchPATCH /dataset/{schema_name}postPOST /translationpatchPATCH /translationsgetGET /usagepostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

CEL Scripting in Template Builder

Un ghid practic pentru scrierea expresiilor CEL în CMS.

Un ghid practic pentru scrierea expresiilor CEL în CMS.


Cum funcționează CEL

CEL (Common Expression Language) este un limbaj de scripting ușor integrat în CMS-ul nostru. Îți permite să scrii expresii dinamice care pot prelua date din documente, citi parametri de URL și calcula valori din mers.

Iată ce se întâmplă când rulează un script CEL:

Scriptul tău                    Motorul                        Rezultat
    |                              |                              |
    v                              v                              v
documents.get("article", "intro") --> Preia din baza de date --> { headline: "Bun venit", body: "..." }
         .headline                --> Extrage câmpul          --> "Bun venit"

Consideră CEL ca pe un limbaj de interogare numai pentru citire. Nu poate modifica nimic în baza de date - doar citește datele și returnează un rezultat calculat. Acest lucru îl face sigur de folosit oriunde în CMS.


Elementele de bază

Fiecare expresie CEL are acces la trei lucruri:

ObiectCe reprezintăExemplu
documentsPreia orice document din CMSdocuments.get("country", "us")
metaInformații despre cererea curentă (localizare, parametri URL)meta.locale, meta.params.slug
schemaDefinițiile câmpurilor documentului curentschema.fields

Auto-referință cu doc

Când scrii expresii CEL în editorul de documente, poți accesa valorile câmpurilor documentului curent folosind obiectul doc. Acest lucru permite câmpuri calculate și referințe între câmpuri.

// Accesează câmpul de preț al documentului curent
doc.price

// Calculează totalul din câmpurile documentului curent
doc.price * doc.quantity

// Condiție bazată pe starea documentului curent
doc.status == "published" ? doc.title : "Ciornă: " + doc.title

Obiectul doc conține toate valorile câmpurilor din documentul editat. Acest lucru este util pentru:

  • Câmpuri calculate (de ex., doc.price * doc.quantity)
  • Logică de afișare condiționată bazată pe starea documentului
  • Expresii de tip validare

Preluarea documentelor

Caracteristica cea mai puternică a CEL este preluarea documentelor din orice loc din CMS.

Obținerea unui singur document

Sintaxă: documents.get(schemaName, identifier)

Să spunem că ai un document article stocat cu identificatorul "welcome-post":

// Stocat în CMS ca: article / welcome-post
{
  "headline": "Bine ai venit pe platforma noastră",
  "author": "Sarah Chen",
  "body": "Suntem încântați să anunțăm...",
  "tags": ["announcement", "news"]
}

Pentru a prelua întregul document:

documents.get("article", "welcome-post")

Returnează:

{
  "headline": "Bine ai venit pe platforma noastră",
  "author": "Sarah Chen",
  "body": "Suntem încântați să anunțăm...",
  "tags": ["announcement", "news"]
}

Pentru a prelua doar titlul:

documents.get("article", "welcome-post").headline

Returnează: "Bine ai venit pe platforma noastră"

Pentru a prelua autorul:

documents.get("article", "welcome-post").author

Returnează: "Sarah Chen"


Utilizarea parametrilor de URL

Când pagina ta are rute dinamice (cum ar fi /articles/[slug]), poți folosi meta.params pentru a obține parametrul din URL și a prelua documentul potrivit.

Dacă cineva vizitează /articles/welcome-post:

documents.get("article", meta.params.slug).headline

Returnează: "Bine ai venit pe platforma noastră"

Așa construiești pagini dinamice - același script CEL funcționează pentru orice articol, folosind slug-ul din URL.


Preluarea mai multor documente

Sintaxă: documents.find(schemaName) sau documents.find(schemaName, filter)

// Obține toate țările
documents.find("country")

Returnează:

[
  { "code": "us", "name": "Statele Unite", "flag": "US" },
  { "code": "sa", "name": "Arabia Saudită", "flag": "SA" },
  { "code": "gb", "name": "Regatul Unit", "flag": "GB" }
]
// Obține țările cu un filtru
documents.find("country", { "where": { "code": "us" } })

Returnează:

[
  { "code": "us", "name": "Statele Unite", "flag": "US" }
]

Traduceri

CEL acceptă preluarea conținutului tradus al documentelor în două moduri: traducere automată bazată pe localizare și căutare explicită de traduceri.

Traducere automată prin meta.locale

Când meta.locale este setat (de ex., din parametrii de rută sau preferințele utilizatorului), documents.get() îmbină automat conținutul tradus:

// Dacă meta.locale este "fr", returnează traducerea în franceză îmbinată cu documentul de bază
documents.get("greeting", "welcome").headline

Cum funcționează:

  1. Preia conținutul documentului de bază
  2. Dacă meta.locale nu este "en" sau "en-US", caută traducerea în tabela translations
  3. Îmbină câmpurile traduse peste conținutul de bază: { ...baseContent, ...translatedContent }

Asta înseamnă că câmpurile traduse suprascriu câmpurile de bază, în timp ce câmpurile netraduse revin la documentul de bază.

Traducere explicită cu documents.translated()

Pentru cazurile în care trebuie să preiei o traducere specifică, indiferent de localizarea curentă:

Sintaxă: documents.translated(schemaName, identifier, locale)

// Preia întotdeauna traducerea în spaniolă
documents.translated("greeting", "welcome", "es").headline

// Preia traducerea pe baza parametrului din URL
documents.translated("product", meta.params.id, meta.params.lang).description

// Compară traduceri
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Exemplu de traducere

Documentele tale de întâmpinare cu traduceri:

// Document de bază: greeting / welcome
{ "headline": "Bun venit", "subheadline": "Bun venit pe platforma noastră" }

// Traducere (limba: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }

// Traducere (limba: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }

Scripturi CEL:

// Cu meta.locale = "fr"
documents.get("greeting", "welcome").headline
// Returnează: "Bienvenue"

// Traducere explicită în spaniolă
documents.translated("greeting", "welcome", "es").headline
// Returnează: "Bienvenido"

// Model de rezervă pentru traduceri lipsă
documents.translated("greeting", "welcome", meta.params.lang) != null
  ? documents.translated("greeting", "welcome", meta.params.lang).headline
  : documents.get("greeting", "welcome").headline

Exemple reale

Exemplul 1: Titlul blocului hero dintr-un alt document

Ai un hero-block care ar trebui să afișeze un titlu preluat dintr-un document article.

Documentul tău article (identificator: "homepage-hero"):

{
  "headline": "Construiește mai rapid, lansează mai inteligent",
  "subheadline": "CMS-ul modern pentru dezvoltatori"
}

Script CEL în câmpul de titlu al blocului hero:

documents.get("article", "homepage-hero").headline

Rezultat: blocul hero afișează "Construiește mai rapid, lansează mai inteligent"


Exemplul 2: Numele țării din cod

Construiești o pagină la /countries/[code] și vrei să afișezi numele complet al țării.

Documentele tale country:

// country / us
{ "code": "us", "name": "Statele Unite", "flag": "US", "languages": ["en", "es"] }

// country / sa
{ "code": "sa", "name": "Arabia Saudită", "flag": "SA", "languages": ["ar", "en"] }

Script CEL:

documents.get("country", meta.params.code).name

Când cineva vizitează /countries/us:

  • meta.params.code = "us"
  • Rezultat: "Statele Unite"

Când cineva vizitează /countries/sa:

  • meta.params.code = "sa"
  • Rezultat: "Arabia Saudită"

Exemplul 3: Conținut condițional în funcție de localizare

Afișează titluri diferite în funcție de localizarea utilizatorului.

meta.locale == "ar-SA" ? "Bun venit, tuturor" : "Bun venit"

Dacă localizarea este "ar-SA": returnează "Bun venit, tuturor" Dacă localizarea este orice altceva: returnează "Bun venit"


Exemplul 4: Căutări în lanț de documente

Documentul tău article are un câmp countryCode, iar tu vrei să obții numele complet al țării.

Document article:

{ "headline": "Știri din SUA", "countryCode": "us" }

Script CEL:

documents.get("country", documents.get("article", "us-news").countryCode).name

Ce se întâmplă:

  1. documents.get("article", "us-news") returnează { "headline": "Știri din SUA", "countryCode": "us" }
  2. .countryCode extrage "us"
  3. documents.get("country", "us") returnează { "code": "us", "name": "Statele Unite", ... }
  4. .name extrage "Statele Unite"

Rezultat: "Statele Unite"


Exemplul 5: Valori de rezervă

Dacă un document ar putea să nu existe, poți oferi o valoare de rezervă:

documents.get("article", meta.params.slug) != null
  ? documents.get("article", meta.params.slug).headline
  : "Articolul nu a fost găsit"

Sau verifică dacă un anumit câmp există:

documents.get("article", "intro").author != null
  ? documents.get("article", "intro").author
  : "Autor necunoscut"

Exemplul 6: Lucrul cu liste

Articolul tău are etichete și vrei să verifici dacă există o etichetă specifică:

"featured" in documents.get("article", "welcome-post").tags

Returnează: true dacă articolul are eticheta "featured"

Obține prima etichetă:

documents.get("article", "welcome-post").tags[0]

Returnează: "announcement" (prima etichetă)

Numără etichetele:

size(documents.get("article", "welcome-post").tags)

Returnează: 2 (numărul de etichete)


Rute parametrice și meta.params

Rutele parametrice sunt cheia pentru construirea paginilor dinamice și localizate. Când definești un model de rută precum /{lang}/landingPage, CMS extrage parametrii din URL și îi pune la dispoziție via meta.params.

Cum funcționează parametrii de rută

Definirea modelului de rută: Rutele folosesc sintaxa :paramName sau {paramName} pentru a defini segmente dinamice:

ModelURL exempluParametri extrași
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Asocieri de parametri: Fiecare parametru de rută poate fi asociat cu o schemă de document pentru validare:

{
  "pattern": "/{lang}/landingPage",
  "param_bindings": {
    "lang": "language"
  }
}

Această asociere îi spune CMS-ului:

  1. Extrage segmentul lang din URL
  2. Validează-l față de schema language (caută un document unde content.code se potrivește)
  3. Dacă este valid, pune documentul complet la dispoziție în parametrii rezolvați

Exemplu: Pagină de destinație bazată pe limbă

Configurația rutei:

  • Cale: /{lang}/landingPage
  • Model: /{lang}/landingPage
  • Asocieri de parametri: { "lang": "language" }

Documentele tale greeting:

// greeting / ko
{ "code": "ko", "headline": "Bun venit", "subheadline": "Bun venit pe platforma noastră", "ctaText": "Începe", "ctaUrl": "/ko/get-started" }

// greeting / en
{ "code": "en", "headline": "Bun venit", "subheadline": "Bun venit pe platforma noastră", "ctaText": "Începe", "ctaUrl": "/en/get-started" }

// greeting / ja
{ "code": "ja", "headline": "Bun venit", "subheadline": "Bun venit pe platforma noastră", "ctaText": "Start", "ctaUrl": "/ja/get-started" }

Script CEL pentru a prelua conținutul localizat:

documents.get("greeting", meta.params.lang).headline

Cum se rezolvă:

URLmeta.params.langRezultat
/ko/landingPage"ko""Bun venit"
/en/landingPage"en""Bun venit"
/ja/landingPage"ja""Bun venit"

Model avansat: Rute țară + limbă

Pentru rute precum /{country}/{lang}/products:

Configurația rutei:

{
  "pattern": "/{country}/{lang}/products",
  "param_bindings": {
    "country": "country",
    "lang": "language"
  }
}

Scripturi CEL:

// Obține numele țării
documents.get("country", meta.params.country).name

// Obține lista de produse localizată în funcție de țară
documents.find("product", { "where": { "country": meta.params.country } })

// Combinat: arată salutul specific țării în limba utilizatorului
documents.get("greeting", meta.params.lang).headline + " din " + documents.get("country", meta.params.country).name

Cascadă de validare: CMS validează parametrii ierarhic. Pentru rutele /{country}/{lang}:

  1. Validează parametrul country față de schema country
  2. Validează parametrul lang față de schema language
  3. Opțional validează faptul că lang se află în array-ul country.languages[] (validare ierarhică)

meta.segments - acces brut la calea URL

meta.segments oferă calea URL brută ca un array, util atunci când ai nevoie de acces pozițional fără parametri numiți.

Cum funcționează:

Cale URLmeta.segments
/articles/tech/ai-news["articles", "tech", "ai-news"]
/ko/landingPage["ko", "landingPage"]
/us/en/products/featured["us", "en", "products", "featured"]
/[]

Când folosești meta.segments vs meta.params

Caz de utilizareAbordare recomandată
Parametri numiți din modelul ruteimeta.params.lang
Acces bazat pe pozițiemeta.segments[0]
Obținerea adâncimii căiisize(meta.segments)
Verificarea dacă calea conține un segment"admin" in meta.segments

Exemple cu meta.segments

// Obține primul segment (adesea codul limbii)
meta.segments[0]

// Verifică adâncimea căii
size(meta.segments) > 2 ? "adâncă" : "superficială"

// Verifică dacă suntem în secțiunea de administrare
"admin" in meta.segments ? "mod admin" : "mod public"

// Rezervă: folosește segmentul dacă parametrul nu este asociat
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Referință completă pentru obiectul meta

Obiectul meta conține tot contextul despre cererea curentă:

ProprietateTipDescriere
meta.localestringCodul localizării curente (de ex., "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Parametrii de rută extrași din modelul URL
meta.segmentsstring[]Calea URL împărțită în segmente
meta.docId`string \null`UUID-ul documentului curent (null pentru documente noi)
meta.titlestringTitlul documentului curent

meta.locale

Codul localizării urmează formatul BCP 47 (limbă-regiune):

// Verifică localizarea pentru limbile RTL
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Obține doar partea de limbă
meta.locale.split("-")[0]  // Nu este acceptat - folosește meta.params.lang în schimb

meta.params

Parametrii rutei sunt întotdeauna stringuri. CMS îi validează față de schemele asociate înainte de evaluare:

// Accesează un parametru numit
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Verifică dacă parametrul există
has(meta.params.category)  // true/false

// Folosește-l pentru a prelua un document
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Segmente brute ale URL-ului, ca array:

// Acces pe index (0-based)
meta.segments[0]           // Primul segment
meta.segments[1]           // Al doilea segment

// Verifică lungimea
size(meta.segments)        // Numărul de segmente

// Verifică apartenența
"products" in meta.segments  // Calea include "products"?

meta.docId

UUID-ul documentului curent, util pentru scripturi auto-referențiale:

// Disponibil doar când editezi documente existente
meta.docId != null ? "editare" : "creare nouă"

// Folosește în logică condițională
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Titlul documentului curent:

// Folosește pentru afișare
"În editare: " + meta.title

// Condițional în funcție de titlu
meta.title.contains("Draft") ? "în lucru" : "publicat"

documents.ref() - căutări în lanț

Pentru un sintaxă mai curată când schema este cunoscută, dar identificatorul este dinamic:

// Abordare tradițională
documents.get("airports", meta.params.code).name

// Folosind ref() - schema separată de identificatorul dinamic
documents.ref("airports").get(meta.params.code).name

Ambele sunt echivalente, dar ref() face partea dinamică mai clară.


Ghid rapid

Preluarea documentelor

documents.get("schema", "identifier")       // Preia un document
documents.get("schema", "id").fieldName     // Preia un câmp specific
documents.find("schema")                    // Preia toate documentele
documents.find("schema", { "where": {...}}) // Interogare filtrată
documents.ref("schema").get(identifier)     // Căutare în lanț
documents.translated("schema", "id", "fr")  // Preia cu localizare explicită

Variabile de context

meta.locale          // "en-US", "ar-SA", etc.
meta.params.xyz      // Parametrul de URL numit "xyz"
meta.segments        // Calea URL ca array: ["articles", "intro"]
meta.segments[0]     // Primul segment de cale
meta.docId           // ID-ul documentului curent (sau null)
meta.title           // Titlul documentului curent
doc.fieldName        // Valoarea câmpului documentului curent (în contextul editorului)

Operatori

// Comparație
==  !=  <  <=  >  >=

// Logică
&&  ||  !

// Ternar (if-else)
condiție ? valoareDacăAdevărat : valoareDacăFals

// Apartenență
"valoare" in listOrMap

Funcții comune

size(list)                    // Numără elementele
size(string)                  // Lungimea stringului
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Verifică dacă proprietatea există
hasProperty(obj, "key")       // Verifică dacă obiectul are cheia (sintaxă alternativă)

Mesaje de eroare

Dacă ceva nu merge, vei vedea unul dintre acestea:

EroareCe înseamnă
SYNTAX_ERRORO greșeală de scriere în script (ghilimele lipsă, operator greșit)
TYPE_ERRORCombini tipuri care nu funcționează împreună
RUNTIME_ERRORScriptul a rulat, dar a întâmpinat o problemă (variabilă nedefinită)
FETCH_LIMIT_EXCEEDEDPreiei prea multe documente (maxim 50)
TIMEOUTScriptul a durat prea mult (maxim 5 secunde)
AST_DEPTH_EXCEEDEDExpresia este prea adânc imbricată (adâncime maximă: 50)
SCRIPT_TOO_LONGScriptul depășește limita de 5000 de caractere

Extensibilitate și capabilități viitoare

Motorul CEL este conceput pentru extensibilitate. Capacitățile planificate pentru viitor includ:

În plan: integrare cu server MCP

// Viitor: apelarea serviciilor externe via MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

În plan: capabilități AI

// Viitor: generare de conținut cu AI
ai.summarize(documents.get("article", meta.params.id).body, 100)
ai.translate(meta.params.text, meta.params.targetLang)
ai.classify(meta.params.input, ["pozitiv", "negativ", "neutru"])

Aceste capabilități vor fi adăugate prin sistemul de funcții înregistrate, menținând compatibilitatea inversă cu scripturile existente.


Sfaturi

  1. Folosește completarea automată - Tastează documents. sau meta. și editorul îți va arăta opțiunile disponibile
  2. Începe simplu - Testează mai întâi cu documents.get("schema", "id"), apoi adaugă .fieldName
  3. Verifică pentru null - Dacă un document ar putea să nu existe, adaugă o rezervă cu != null ? ... : ...
  4. Nu prelua în exces - Fiecare documents.get() sau documents.find() se contorizează în limita de 50 de preluări
  5. Preferă meta.params în loc de meta.segments - Parametrii numiți sunt validați și mai de încredere
  6. Folosește has() pentru parametri opționali - Verifică has(meta.params.category) înainte de a accesa
  7. Folosește documents.ref() pentru identificatori dinamici - Sintaxă mai clară când schema este statică, dar identificatorul este dinamic
  8. Folosește doc.fieldName pentru auto-referințe - Accesează câmpurile documentului curent în expresiile calculate

Referințe între documente

Această secțiune acoperă modele avansate pentru legarea documentelor și construirea structurilor de conținut relaționale.

Model de referință de bază

Forma cea mai simplă: un document face referire la altul prin identificator.

// Articolul stochează ID-ul autorului, preia numele autorului
documents.get("author", documents.get("article", "intro").authorId).name

Căutări în lanț cu documents.ref()

Pentru o sintaxă mai curată când identificatorul este dinamic:

// Abordare tradițională
documents.get("country", documents.get("airport", meta.params.code).countryCode).name

// Folosind ref() - mai clar când schema este cunoscută, dar identificatorul este dinamic
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name

Lanțuri de referințe pe mai multe niveluri

Construiește relații profunde prin înlănțuirea mai multor preluări:

// Aeroport → Țară → Regiune → Continent
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Referință cu traducere

Combină referințele de documente cu traduceri:

// Obține numele localizat al țării pentru un aeroport
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Modele de referință după caz de utilizare

Modelul 1: Căutare prin cheie externă

Documentul stochează un ID care face referire la alt document.

// article / tech-news
{ "title": "Actualizare tech", "authorId": "author-123", "categoryId": "cat-tech" }
// Rezolvă numele autorului
documents.get("author", documents.get("article", meta.params.slug).authorId).name

// Rezolvă categoria cu rezervă
documents.get("article", meta.params.slug).categoryId != null
  ? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
  : "Fără categorie"

Modelul 2: Referințe bazate pe cod

Documentele se referă între ele prin coduri semantice mai degrabă decât UUID-uri.

// airport / JFK
{ "code": "JFK", "name": "John F. Kennedy International", "countryCode": "us" }

// country / us
{ "code": "us", "name": "Statele Unite", "currencyCode": "usd" }

// currency / usd
{ "code": "usd", "symbol": "$", "name": "Dolarul SUA" }
// Lanț Aeroport → Țară → Monedă
documents.get("currency",
  documents.get("country",
    documents.get("airport", meta.params.code).countryCode
  ).currencyCode
).symbol
// Pentru JFK: returnează "$"

Modelul 3: Auto-referință cu contextul doc

Folosește doc pentru câmpuri calculate care fac referire la alte documente pe baza valorilor documentului curent.

// Într-un document de produs, preia detalii despre categoria asociată
documents.get("category", doc.categoryId).description

// Cost de livrare calculat pe baza țării de origine a produsului
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Modelul 4: Referințe bidirecționale

Când documentele se referă reciproc, ai grijă la limitele de preluare.

// Obține autorul articolului, apoi alte articole ale autorului (atenție la numărul de preluări)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })

Modelul 5: Referințe polimorfice

Când un câmp poate face referire la scheme diferite:

// content-block / hero-1
{ "type": "hero", "sourceType": "article", "sourceId": "welcome-post" }

// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Căutare dinamică a schemei în funcție de 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

Urmărirea dependențelor

Fiecare apel documents.get(), documents.find() și documents.ref().get() este urmărit pentru invalidarea cache-ului. Când un document referit se schimbă, CMS știe ce expresii CEL trebuie reevaluate.

Dependențele urmărite includ:

  • get: schema:identifier - dependență de document specific
  • ref: schema:identifier - la fel ca get, prin sintaxa în lanț
  • query: schema:* - dependență la nivel de schemă (orice document din schemă)

Cele mai bune practici pentru referințe

  1. Minimizează adâncimea lanțului - fiecare nivel adaugă latență și preluări
  2. Cachează rezultatele intermediare - dacă ai nevoie de aceeași valoare imbricată de două ori, preia părintele o singură dată
  3. Folosește verificări de null - referințele se pot rupe dacă documentele sunt șterse
  4. Preferă codurile în locul UUID-urilor - codurile sunt ușor de citit în expresii și stabile între medii
  5. Monitorizează limitele de preluare - lanțurile complexe pot atinge rapid limita de 50 de preluări
// Greșit: preia același document de două ori
documents.get("author", documents.get("article", "intro").authorId).name + " - " +
documents.get("author", documents.get("article", "intro").authorId).bio

// Mai bine: folosește o condiție pentru a verifica o singură dată
documents.get("article", "intro").authorId != null
  ? documents.get("author", documents.get("article", "intro").authorId).name
  : "Autor necunoscut"

Anexa A: Exemplu complet de rută parametrică

Această prezentare creează o pagină de destinație multilingvă accesibilă la /{lang}/landingPage.

Pasul 1: Creează schema documentului Greeting

În admin-ul CMS, creează o schemă personalizată numită 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" }
  ]
}

Pasul 2: Creează documentele Greeting

Creează documente pentru fiecare limbă:

Document: greeting/ko

{
  "code": "ko",
  "headline": "Bun venit",
  "subheadline": "Bun venit pe platforma noastră",
  "ctaText": "Începe",
  "ctaUrl": "/ko/get-started"
}

Document: greeting/en

{
  "code": "en",
  "headline": "Bun venit",
  "subheadline": "Bun venit pe platforma noastră",
  "ctaText": "Începe",
  "ctaUrl": "/en/get-started"
}

Document: greeting/ja

{
  "code": "ja",
  "headline": "Bun venit",
  "subheadline": "Bun venit pe platforma noastră",
  "ctaText": "Start",
  "ctaUrl": "/ja/get-started"
}

Pasul 3: Creează pagina

Creează o pagină cu următoarea configurație:

  • Cale/Model: /{lang}/landingPage
  • Stare: Live
  • Mapări pentru segmentele dinamice: mapare lang → componenta language
  {
    "lang": "language"
  }

Pasul 4: Adaugă blocuri cu scripturi CEL

Adaugă un bloc hero în rută cu aceste scripturi CEL pentru fiecare câmp:

Câmpul Headline:

documents.get("greeting", meta.params.lang).headline

Câmpul Subheadline:

documents.get("greeting", meta.params.lang).subheadline

Câmpul CTA Text:

documents.get("greeting", meta.params.lang).ctaText

Câmpul CTA URL:

documents.get("greeting", meta.params.lang).ctaUrl

Pasul 5: Consumă în Next.js

Adaugă o rută catch-all. ParametricRoutePage rezolvă pagina, extrage meta.params din URL, evaluează legăturile CEL pe server și redă fiecare bloc prin registrul tău — nu construiești singur contextul meta și nici nu apelezi clientul de nivel inferior.

// 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 })}
    />
  );
}

Pasul 6: Testează rutele

Vizitează aceste URL-uri pentru a vedea conținutul localizat:

URLTitlul așteptat
/ko/landingPage환영
/en/landingPageWelcome
/ja/landingPageいらっしゃいませ

Cum funcționează rezolvarea

Când un utilizator vizitează /ko/landingPage:

  1. Potrivirea rutei: CMS potrivește modelul /{lang}/landingPage
  2. Extracția parametrului: meta.params.lang = "ko"
  3. Validare: CMS validează că "ko" există în schema language
  4. Evaluare CEL: Scripturi precum documents.get("greeting", meta.params.lang) se rezolvă la conținutul coreean
  5. Răspuns: Blocurile localizate sunt returnate către client

Anexa B: Referință tehnică

Interfața CelMeta (TypeScript)

interface CelMeta {
  /** Codul localizării curente (de ex., 'en-US') */
  locale: string;
  /** Parametrii de rută extrași din URL */
  params: Record<string, string>;
  /** Segmentele căii URL */
  segments: string[];
  /** ID-ul documentului curent (dacă editezi un document existent) */
  docId: string | null;
  /** Titlul documentului curent */
  title: string;
}

Algoritmul de extragere a parametrilor

Funcția extractParams procesează căile URL:

Model: /{country}/{lang}/products
Cale:   /us/en/products

Algoritm:
1. Normalizează ambele (elimină slash-urile finale)
2. Împarte în segmente: ["us", "en", "products"] și ["{country}", "{lang}", "products"]
3. Potrivește numărul segmentelor (trebuie să fie egal)
4. Pentru fiecare pereche de segmente:
   - Dacă modelul începe cu : sau {}, extrage ca parametru
   - Altfel, trebuie să se potrivească exact
5. Returnează: { country: "us", lang: "en" }

Formate de asociere a parametrilor acceptate

// Asociere simplă (folosește câmpul "code" pentru căutare)
{ "lang": "language" }

// Asociere detaliată (câmp slug personalizat)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Prioritatea de căutare a documentelor

Când preiei prin documents.get(schema, identifier):

  1. Potrivire UUID: dacă identificatorul este un UUID valid, preia după id
  2. Câmpul code: verifică câmpul content.code
  3. Câmpul slug: verifică câmpul content.slug
  4. Potrivire de titlu: verifică câmpul title

Acest lucru permite referințe flexibile la documente prin orice identificator unic.

Continue Reading
Previous‹Install Profound CMS as a proxyNextProject Scaffolding›