profound-logoProfound CMS
⌘K
Admin
Theme
DocsGuidaBlogPhilosophy
DocsGuidaBlogPhilosophy

Hybrid

Instradamento parametricoTypes of ComponentsSetup server sent events (SSE) content refetchInstall Profound CMS as a proxyCEL Scripting in Template BuilderProject ScaffoldingMedia Library

Senza testa

Guida rapidaSplit Screen JSON Component Builder with LLMComponent Zod Pull

REST API

REST API OverviewgetConnect your websitegetGET /routesgetOttieni percorsogetGET /blocksgetGET /blocks/with-cel-cachegetGET /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

Una guida pratica alla scrittura di espressioni CEL nel CMS.

Guida pratica alla scrittura di espressioni CEL nel CMS.


Come funziona CEL

CEL (Common Expression Language) è un linguaggio di scripting leggero integrato nel nostro CMS. Consente di scrivere espressioni dinamiche che possono recuperare dati dai documenti, leggere i parametri URL e calcolare valori al volo.

Ecco cosa succede quando viene eseguito uno script CEL:

Il tuo script                   Il motore                      Risultato
    |                              |                              |
    v                              v                              v
documents.get("article", "intro") --> Recupera dal database --> { headline: "Welcome", body: "..." }
         .headline                --> Estrae il campo        --> "Welcome"

Considera CEL come un linguaggio di query in sola lettura. Non può modificare nulla nel database: legge semplicemente i dati e restituisce un risultato calcolato. Questo lo rende sicuro da usare in qualsiasi area del CMS.


Gli elementi fondamentali

Ogni espressione CEL ha accesso a tre elementi:

OggettoChe cos'èEsempio
documentsRecupera qualsiasi documento dal CMSdocuments.get("country", "us")
metaInformazioni sulla richiesta corrente (locale, parametri URL)meta.locale, meta.params.slug
schemaDefinizioni dei campi del documento correnteschema.fields

Riferimenti al documento corrente con doc

Quando scrivi espressioni CEL all'interno di un editor di documenti, puoi accedere ai valori dei campi del documento corrente tramite l'oggetto doc. Questo consente di creare campi calcolati e riferimenti tra campi.

// Accede al campo price del documento corrente
doc.price

// Calcola il totale dai campi del documento corrente
doc.price * doc.quantity

// Condizione basata sullo stato del documento corrente
doc.status == "published" ? doc.title : "Bozza: " + doc.title

L'oggetto doc contiene tutti i valori dei campi del documento modificato. È utile per:

  • Campi calcolati (ad esempio, doc.price * doc.quantity)
  • Logica di visualizzazione condizionale basata sullo stato del documento
  • Espressioni in stile validazione

Recupero dei documenti

La funzionalità più potente di CEL è il recupero di documenti da qualsiasi punto del CMS.

Recuperare un singolo documento

Sintassi: documents.get(schemaName, identifier)

Supponiamo di avere un documento article memorizzato con l'identificatore "welcome-post":

// Memorizzato nel CMS come: article / welcome-post
{
  "headline": "Welcome to Our Platform",
  "author": "Sarah Chen",
  "body": "We're excited to announce...",
  "tags": ["announcement", "news"]
}

Per recuperare l'intero documento:

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

Restituisce:

{
  "headline": "Welcome to Our Platform",
  "author": "Sarah Chen",
  "body": "We're excited to announce...",
  "tags": ["announcement", "news"]
}

Per recuperare solo il titolo:

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

Restituisce: "Welcome to Our Platform"

Per recuperare l'autore:

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

Restituisce: "Sarah Chen"


Utilizzo dei parametri URL

Quando la pagina presenta route dinamiche (come /articles/[slug]), puoi usare meta.params per ottenere il parametro URL e recuperare il documento corretto.

Se qualcuno visita /articles/welcome-post:

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

Restituisce: "Welcome to Our Platform"

È così che si costruiscono pagine dinamiche: lo stesso script CEL funziona per qualsiasi articolo, usando semplicemente lo slug presente nell'URL.


Recuperare più documenti

Sintassi: documents.find(schemaName) oppure documents.find(schemaName, filter)

// Recupera tutti i paesi
documents.find("country")

Restituisce:

[
  { "code": "us", "name": "United States", "flag": "US" },
  { "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
  { "code": "gb", "name": "United Kingdom", "flag": "GB" }
]
// Recupera i paesi applicando un filtro
documents.find("country", { "where": { "code": "us" } })

Restituisce:

[
  { "code": "us", "name": "United States", "flag": "US" }
]

Traduzioni

CEL supporta il recupero di contenuti tradotti in due modi: traduzione automatica basata sul locale e ricerca esplicita della traduzione.

Traduzione automatica tramite meta.locale

Quando meta.locale è impostato (ad esempio tramite parametri di route o preferenze dell'utente), documents.get() unisce automaticamente il contenuto tradotto:

// Se meta.locale è "fr", restituisce la traduzione francese unita al documento di base
documents.get("greeting", "welcome").headline

Come funziona:

  1. Recupera il contenuto del documento di base
  2. Se meta.locale non è "en" o "en-US", cerca la traduzione nella tabella translations
  3. Unisce i campi tradotti al contenuto di base: { ...baseContent, ...translatedContent }

Questo significa che i campi tradotti sostituiscono quelli di base, mentre i campi non tradotti usano il documento di base come fallback.

Traduzione esplicita con documents.translated()

Quando devi recuperare una traduzione specifica indipendentemente dal locale corrente:

Sintassi: documents.translated(schemaName, identifier, locale)

// Recupera sempre la traduzione spagnola
documents.translated("greeting", "welcome", "es").headline

// Recupera la traduzione in base a un parametro URL
documents.translated("product", meta.params.id, meta.params.lang).description

// Confronta le traduzioni
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Esempio di traduzione

Documenti greeting con traduzioni:

// Documento di base: greeting / welcome
{ "headline": "Welcome", "subheadline": "Welcome to our platform" }

// Traduzione (lingua: "fr")
{ "headline": "Bienvenue", "subheadline": "Bienvenue sur notre plateforme" }

// Traduzione (lingua: "es")
{ "headline": "Bienvenido", "subheadline": "Bienvenido a nuestra plataforma" }

Script CEL:

// Con meta.locale = "fr"
documents.get("greeting", "welcome").headline
// Restituisce: "Bienvenue"

// Traduzione spagnola esplicita
documents.translated("greeting", "welcome", "es").headline
// Restituisce: "Bienvenido"

// Pattern di fallback per traduzioni mancanti
documents.translated("greeting", "welcome", meta.params.lang) != null
  ? documents.translated("greeting", "welcome", meta.params.lang).headline
  : documents.get("greeting", "welcome").headline

Esempi reali

Esempio 1: titolo di un blocco hero da un altro documento

Hai un hero-block che deve visualizzare un titolo recuperato da un documento article.

Il documento article (identificatore: "homepage-hero"):

{
  "headline": "Build Faster, Ship Smarter",
  "subheadline": "The modern CMS for developers"
}

Script CEL nel campo titolo del blocco hero:

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

Risultato: il blocco hero visualizza "Build Faster, Ship Smarter"


Esempio 2: nome del paese a partire dal codice

Stai creando una pagina in /countries/[code] e vuoi visualizzare il nome completo del paese.

I documenti country:

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

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

Script CEL:

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

Quando qualcuno visita /countries/us:

  • meta.params.code = "us"
  • Risultato: "United States"

Quando qualcuno visita /countries/sa:

  • meta.params.code = "sa"
  • Risultato: "Saudi Arabia"

Esempio 3: contenuto condizionale basato sul locale

Mostra titoli diversi in base al locale dell'utente.

meta.locale == "ar-SA" ? "Welcome, everyone" : "Welcome"

Se il locale è "ar-SA": restituisce "Welcome, everyone" Se il locale è diverso: restituisce "Welcome"


Esempio 4: recuperi concatenati di documenti

Il tuo article ha un campo countryCode e vuoi ottenere il nome completo del paese.

Documento article:

{ "headline": "News from the US", "countryCode": "us" }

Script CEL:

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

Cosa succede:

  1. documents.get("article", "us-news") restituisce { "headline": "News from the US", "countryCode": "us" }
  2. .countryCode estrae "us"
  3. documents.get("country", "us") restituisce { "code": "us", "name": "United States", ... }
  4. .name estrae "United States"

Risultato: "United States"


Esempio 5: valori di fallback

Se un documento potrebbe non esistere, puoi fornire un fallback:

documents.get("article", meta.params.slug) != null
  ? documents.get("article", meta.params.slug).headline
  : "Article Not Found"

Oppure verifica se esiste un campo specifico:

documents.get("article", "intro").author != null
  ? documents.get("article", "intro").author
  : "Unknown Author"

Esempio 6: lavorare con le liste

Il tuo articolo ha dei tag e vuoi verificare se esiste un tag specifico:

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

Restituisce: true se l'articolo ha il tag "featured"

Ottieni il primo tag:

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

Restituisce: "announcement" (il primo tag)

Conta i tag:

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

Restituisce: 2 (numero di tag)


Route parametriche e meta.params

Le route parametriche sono fondamentali per creare pagine dinamiche e localizzate. Quando definisci un pattern come /{lang}/landingPage, il CMS estrae i parametri dall'URL e li rende disponibili tramite meta.params.

Come funzionano i parametri delle route

Definizione del pattern della route: Le route usano la sintassi :paramName o {paramName} per definire segmenti dinamici:

PatternURL di esempioParametri estratti
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Associazione dei parametri: Ogni parametro della route può essere associato a uno schema di documento per la validazione:

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

Questa associazione indica al CMS di:

  1. Estrarre il segmento lang dall'URL
  2. Validarlo rispetto allo schema language (cerca un documento il cui content.code corrisponda)
  3. Se valido, rendere disponibile il documento completo nei parametri risolti

Esempio: landing page basata sulla lingua

Configurazione della route:

  • Percorso: /{lang}/landingPage
  • Pattern: /{lang}/landingPage
  • Associazioni dei parametri: { "lang": "language" }

I tuoi documenti greeting:

// 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" }

Script CEL per recuperare il contenuto localizzato:

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

Come viene risolto:

URLmeta.params.langRisultato
/ko/landingPage"ko""Welcome"
/en/landingPage"en""Welcome"
/ja/landingPage"ja""Welcome"

Pattern avanzato: route paese + lingua

Per route come /{country}/{lang}/products:

Configurazione della route:

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

Script CEL:

// Ottieni il nome del paese
documents.get("country", meta.params.country).name

// Ottieni l'elenco localizzato dei prodotti in base al paese
documents.find("product", { "where": { "country": meta.params.country } })

// Combinato: mostra un saluto specifico per il paese nella lingua dell'utente
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name

Cascata di validazione: Il CMS valida i parametri gerarchicamente. Per le route /{country}/{lang}:

  1. Valida il parametro country rispetto allo schema country
  2. Valida il parametro lang rispetto allo schema language
  3. Facoltativamente verifica che lang sia presente nell'array country.languages[] (validazione gerarchica)

meta.segments - accesso al percorso URL grezzo

meta.segments fornisce il percorso URL grezzo come array, utile quando serve un accesso posizionale senza parametri nominati.

Come funziona:

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

Quando usare meta.segments invece di meta.params

Caso d'usoApproccio migliore
Parametri nominati dal pattern della routemeta.params.lang
Accesso basato sulla posizionemeta.segments[0]
Ottenere la profondità del percorsosize(meta.segments)
Verificare se il percorso contiene un segmento"admin" in meta.segments

Esempi con meta.segments

// Ottieni il primo segmento (spesso il codice della lingua)
meta.segments[0]

// Verifica la profondità del percorso
size(meta.segments) > 2 ? "deep" : "shallow"

// Verifica se siamo nella sezione amministrativa
"admin" in meta.segments ? "admin mode" : "public mode"

// Fallback: usa il segmento se il parametro non è associato
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Riferimento completo all'oggetto meta

L'oggetto meta contiene tutto il contesto della richiesta corrente:

ProprietàTipoDescrizione
meta.localestringCodice del locale corrente (ad esempio "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Parametri della route estratti dall'URL
meta.segmentsstring[]Percorso URL suddiviso in segmenti
meta.docIdstring | nullUUID del documento corrente (null per i nuovi documenti)
meta.titlestringTitolo del documento corrente

meta.locale

Il codice del locale segue il formato BCP 47 (lingua-regione):

// Verifica il locale per le lingue RTL
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Ottieni solo la parte relativa alla lingua
meta.locale.split("-")[0]  // Non supportato - usa invece meta.params.lang

meta.params

I parametri delle route sono sempre stringhe. Prima della valutazione, il CMS li valida rispetto agli schemi associati:

// Accedi al parametro nominato
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Verifica se il parametro esiste
has(meta.params.category)  // true/false

// Usa il parametro per recuperare un documento
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Segmenti URL grezzi come array:

// Accedi tramite indice (a partire da 0)
meta.segments[0]           // Primo segmento
meta.segments[1]           // Secondo segmento

// Verifica la lunghezza
size(meta.segments)        // Numero di segmenti

// Verifica l'appartenenza
"products" in meta.segments  // Il percorso include "products"?

meta.docId

L'UUID del documento corrente, utile per gli script autoreferenziali:

// Disponibile solo durante la modifica di documenti esistenti
meta.docId != null ? "editing" : "creating new"

// Usa nella logica condizionale
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Il titolo del documento corrente:

// Usa per la visualizzazione
"Editing: " + meta.title

// Condizione basata sul titolo
meta.title.contains("Draft") ? "work in progress" : "published"

documents.ref() - recuperi concatenati

Per una sintassi più pulita quando lo schema è noto ma l'identificatore è dinamico:

// Approccio tradizionale
documents.get("airports", meta.params.code).name

// Utilizzo di ref() - lo schema è separato dall'identificatore dinamico
documents.ref("airports").get(meta.params.code).name

I due approcci sono equivalenti, ma ref() rende più chiara la parte dinamica.


Riferimento rapido

Recupero dei documenti

documents.get("schema", "identifier")       // Recupera un documento
documents.get("schema", "id").fieldName     // Recupera un campo specifico
documents.find("schema")                    // Recupera tutti i documenti
documents.find("schema", { "where": {...}}) // Query filtrata
documents.ref("schema").get(identifier)     // Recupero concatenato
documents.translated("schema", "id", "fr")  // Recupera con locale esplicito

Variabili di contesto

meta.locale          // "en-US", "ar-SA", ecc.
meta.params.xyz      // Parametro URL denominato "xyz"
meta.segments        // Percorso URL come array: ["articles", "intro"]
meta.segments[0]     // Primo segmento del percorso
meta.docId           // ID del documento corrente (o null)
meta.title           // Titolo del documento corrente
doc.fieldName        // Valore del campo del documento corrente (nel contesto dell'editor)

Operatori

// Confronto
==  !=  <  <=  >  >=

// Logica
&&  ||  !

// Ternario (if-else)
condition ? valueIfTrue : valueIfFalse

// Appartenenza
"value" in listOrMap

Funzioni comuni

size(list)                    // Conta gli elementi
size(string)                  // Lunghezza della stringa
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Verifica se la proprietà esiste
hasProperty(obj, "key")       // Verifica se l'oggetto contiene la chiave (sintassi alternativa)

Messaggi di errore

Se qualcosa va storto, vedrai uno dei seguenti messaggi:

ErroreSignificato
SYNTAX_ERRORErrore di battitura nello script (virgolette mancanti, operatore errato)
TYPE_ERRORStai combinando tipi incompatibili
RUNTIME_ERRORLo script è stato eseguito, ma ha riscontrato un problema (variabile non definita)
FETCH_LIMIT_EXCEEDEDStai recuperando troppi documenti (massimo 50)
TIMEOUTLo script ha impiegato troppo tempo (massimo 5 secondi)
AST_DEPTH_EXCEEDEDL'espressione è annidata troppo profondamente (profondità massima: 50)
SCRIPT_TOO_LONGLo script supera il limite di 5000 caratteri

Estensibilità e funzionalità future

Il motore CEL è progettato per essere estensibile. Tra le funzionalità future previste figurano:

In programma: integrazione con il server MCP

// Futuro: chiama servizi esterni tramite MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

In programma: funzionalità di IA

// Futuro: generazione di contenuti basata sull'IA
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"])

Queste funzionalità verranno aggiunte tramite il sistema di funzioni registrate, mantenendo la compatibilità con gli script esistenti.


Suggerimenti

  1. Usa il completamento automatico - Digita documents. o meta. e l'editor mostrerà le opzioni disponibili
  2. Inizia in modo semplice - Prima prova documents.get("schema", "id"), poi aggiungi .fieldName
  3. Controlla i valori null - Se un documento potrebbe non esistere, aggiungi un fallback con != null ? ... : ...
  4. Non recuperare dati inutili - Ogni documents.get() o documents.find() viene conteggiato nel limite di 50 recuperi
  5. Preferisci meta.params a meta.segments - I parametri nominati sono validati e più affidabili
  6. Usa has() per i parametri facoltativi - Verifica has(meta.params.category) prima di accedervi
  7. Usa documents.ref() per gli identificatori dinamici - Sintassi più chiara quando lo schema è statico ma l'identificatore è dinamico
  8. Usa doc.fieldName per i riferimenti al documento corrente - Accedi ai campi del documento corrente nelle espressioni calcolate

Riferimenti tra documenti

Questa sezione illustra pattern avanzati per collegare i documenti e creare strutture di contenuto relazionali.

Pattern di riferimento di base

La forma più semplice: un documento fa riferimento a un altro tramite identificatore.

// L'articolo memorizza l'ID dell'autore; recupera il nome dell'autore
documents.get("author", documents.get("article", "intro").authorId).name

Recuperi concatenati con documents.ref()

Per una sintassi più pulita quando l'identificatore è dinamico:

// Approccio tradizionale
documents.get("country", documents.get("airport", meta.params.code).countryCode).name

// Utilizzo di ref() - più chiaro quando lo schema è noto ma l'identificatore è dinamico
documents.ref("country").get(documents.get("airport", meta.params.code).countryCode).name

Catene di riferimenti multilivello

Crea relazioni profonde concatenando più recuperi:

// Aeroporto → Paese → Regione → Continente
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Riferimenti con traduzione

Combina i riferimenti ai documenti con le traduzioni:

// Ottieni il nome localizzato del paese di un aeroporto
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Pattern di riferimento per caso d'uso

Pattern 1: ricerca tramite chiave esterna

Il documento memorizza un ID che fa riferimento a un altro documento.

// article / tech-news
{ "title": "Tech Update", "authorId": "author-123", "categoryId": "cat-tech" }
// Risolvi il nome dell'autore
documents.get("author", documents.get("article", meta.params.slug).authorId).name

// Risolvi la categoria con fallback
documents.get("article", meta.params.slug).categoryId != null
  ? documents.get("category", documents.get("article", meta.params.slug).categoryId).name
  : "Uncategorized"

Pattern 2: riferimenti basati su codici

I documenti fanno riferimento tra loro tramite codici semantici anziché UUID.

// 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" }
// Catena Aeroporto → Paese → Valuta
documents.get("currency",
  documents.get("country",
    documents.get("airport", meta.params.code).countryCode
  ).currencyCode
).symbol
// Per JFK: restituisce "$"

Pattern 3: autoreferenzialità con il contesto doc

Usa doc per i campi calcolati che fanno riferimento ad altri documenti in base ai valori del documento corrente.

// In un documento product, recupera i dettagli della categoria correlata
documents.get("category", doc.categoryId).description

// Costo di spedizione calcolato in base al paese di origine del prodotto
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Pattern 4: riferimenti bidirezionali

Quando i documenti fanno riferimento l'uno all'altro, presta attenzione ai limiti di recupero.

// Recupera l'autore dell'articolo, poi gli altri articoli dell'autore (controlla il numero di recuperi!)
documents.find("article", { "where": { "authorId": documents.get("article", meta.params.slug).authorId } })

Pattern 5: riferimenti polimorfici

Quando un campo può fare riferimento a schemi diversi:

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

// content-block / hero-2
{ "type": "hero", "sourceType": "product", "sourceId": "featured-item" }
// Ricerca dinamica dello schema in base a 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

Tracciamento delle dipendenze

Ogni chiamata a documents.get(), documents.find() e documents.ref().get() viene tracciata per l'invalidazione della cache. Quando cambia un documento referenziato, il CMS sa quali espressioni CEL devono essere rivalutate.

Le dipendenze tracciate includono:

  • get: schema:identifier - Dipendenza da un documento specifico
  • ref: schema:identifier - Come get, tramite sintassi concatenata
  • query: schema:* - Dipendenza a livello di schema (qualsiasi documento nello schema)

Buone pratiche per i riferimenti

  1. Riduci al minimo la profondità delle catene - Ogni livello aumenta latenza e numero di recuperi
  2. Memorizza nella cache i risultati intermedi - Se ti serve due volte lo stesso valore annidato, recupera il documento padre una sola volta
  3. Usa i controlli null - I riferimenti possono interrompersi se i documenti vengono eliminati
  4. Preferisci i codici agli UUID - I codici sono leggibili nelle espressioni e stabili tra gli ambienti
  5. Tieni sotto controllo i limiti - Le catene complesse possono raggiungere rapidamente il limite di 50 recuperi

Appendice A: esempio completo di route parametrica

Questa procedura crea una landing page multilingue accessibile all'indirizzo /{lang}/landingPage.

Passaggio 1: crea lo schema del documento Greeting

Nell'amministrazione del CMS, crea uno schema personalizzato chiamato 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" }
  ]
}

Passaggio 2: crea i documenti Greeting

Crea un documento per ogni lingua:

Documento: greeting/ko

{
  "code": "ko",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Get Started",
  "ctaUrl": "/ko/get-started"
}

Documento: greeting/en

{
  "code": "en",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Get Started",
  "ctaUrl": "/en/get-started"
}

Documento: greeting/ja

{
  "code": "ja",
  "headline": "Welcome",
  "subheadline": "Welcome to our platform",
  "ctaText": "Start",
  "ctaUrl": "/ja/get-started"
}

Passaggio 3: crea la pagina

Crea una pagina con la seguente configurazione:

  • Percorso/Pattern: /{lang}/landingPage
  • Stato: Pubblicata
  • Mappature dei segmenti dinamici: associa lang al componente language
  {
    "lang": "language"
  }

Passaggio 4: aggiungi blocchi con script CEL

Aggiungi un blocco hero alla route con questi script CEL per ciascun campo:

Campo Headline:

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

Campo Subheadline:

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

Campo CTA Text:

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

Campo CTA URL:

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

Passaggio 5: utilizza Next.js

Aggiungi una route catch-all. ParametricRoutePage risolve la pagina, estrae meta.params dall'URL, valuta i binding CEL lato server e renderizza ogni blocco tramite il registro: non devi creare il contesto meta né chiamare direttamente il client di basso livello.

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

Passaggio 6: verifica le route

Visita questi URL per visualizzare i contenuti localizzati:

URLTitolo previsto
/ko/landingPage환영
/en/landingPageWelcome
/ja/landingPageいらっしゃいませ

Come funziona la risoluzione

Quando un utente visita /ko/landingPage:

  1. Corrispondenza della route: il CMS trova il pattern /{lang}/landingPage
  2. Estrazione del parametro: meta.params.lang = "ko"
  3. Validazione: il CMS verifica che "ko" esista nello schema language
  4. Valutazione CEL: script come documents.get("greeting", meta.params.lang) vengono risolti nel contenuto coreano
  5. Risposta: i blocchi localizzati vengono restituiti al client

Appendice B: riferimento tecnico

Interfaccia CelMeta (TypeScript)

interface CelMeta {
  /** Codice del locale corrente (ad esempio 'en-US') */
  locale: string;
  /** Parametri della route estratti dall'URL */
  params: Record<string, string>;
  /** Segmenti del percorso URL */
  segments: string[];
  /** ID del documento corrente (se si modifica un documento esistente) */
  docId: string | null;
  /** Titolo del documento corrente */
  title: string;
}

Algoritmo di estrazione dei parametri

La funzione extractParams elabora i percorsi URL:

Pattern: /{country}/{lang}/products
Percorso: /us/en/products

Algoritmo:
1. Normalizza entrambi (rimuove le barre finali)
2. Divide in segmenti: ["us", "en", "products"] e ["{country}", "{lang}", "products"]
3. Confronta il numero di segmenti (deve essere uguale)
4. Per ogni coppia di segmenti:
   - Se il pattern inizia con : o {}, estrae il parametro
   - Altrimenti, deve corrispondere esattamente
5. Restituisce: { country: "us", lang: "en" }

Formati supportati per l'associazione dei parametri

// Associazione semplice (usa il campo "code" per la ricerca)
{ "lang": "language" }

// Associazione dettagliata (campo slug personalizzato)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Priorità nella ricerca dei documenti

Quando recuperi tramite documents.get(schema, identifier):

  1. Corrispondenza UUID: se l'identificatore è un UUID valido, recupera tramite id
  2. Campo code: controlla il campo content.code
  3. Campo slug: controlla il campo content.slug
  4. Corrispondenza del titolo: controlla il campo title

Questo consente di fare riferimento ai documenti in modo flessibile tramite qualsiasi identificatore univoco.

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