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 proxySkriptovanie v nástroji na tvorbu šablónProject ScaffoldingKnižnica médií

Headless

Rýchly štartSplit Screen JSON Component Builder with LLMComponent Zod Pull

REST API

Prehľad REST APIgetConnect your websitegetZískanie trásgetZískanie trasygetZískaj blokygetGET /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

Skriptovanie v nástroji na tvorbu šablón

Praktická príručka na písanie výrazov CEL v CMS.

Praktická príručka na písanie výrazov CEL v CMS.


Ako funguje CEL

CEL (Common Expression Language) je ľahký skriptovací jazyk zabudovaný do nášho CMS. Umožňuje písať dynamické výrazy, ktoré získavajú údaje z dokumentov, čítajú parametre URL a priebežne vypočítavajú hodnoty.

Čo sa stane pri spustení skriptu CEL:

Váš skript                     Stroj                          Výsledok
documents.get("article", "intro") --> Načíta z databázy --> { headline: "Welcome", body: "..." }
         .headline                --> Extrahuje pole      --> "Welcome"

CEL si môžete predstaviť ako jazyk dotazov iba na čítanie. Nemôže meniť nič v databáze – iba číta údaje a vracia vypočítaný výsledok. Preto je bezpečné používať ho kdekoľvek v CMS.


Základné stavebné prvky

Každý výraz CEL má prístup k trom veciam:

ObjektČo predstavujePríklad
documentsNačítanie ľubovoľného dokumentu z CMSdocuments.get("country", "us")
metaInformácie o aktuálnej požiadavke (lokalizácia, parametre URL)meta.locale, meta.params.slug
schemaDefinície polí aktuálneho dokumentuschema.fields

Odkazovanie na aktuálny dokument pomocou doc

Pri písaní výrazov CEL v editore dokumentu môžete k hodnotám polí aktuálneho dokumentu pristupovať pomocou objektu doc. To umožňuje vytvárať vypočítavané polia a odkazy medzi poľami.

// Prístup k poľu price aktuálneho dokumentu
doc.price

// Výpočet súčtu z polí aktuálneho dokumentu
doc.price * doc.quantity

// Podmienka založená na stave aktuálneho dokumentu
doc.status == "published" ? doc.title : "Draft: " + doc.title

Objekt doc obsahuje všetky hodnoty polí upravovaného dokumentu. Je užitočný pri:

  • vypočítavaných poliach (napr. doc.price * doc.quantity),
  • podmienenej logike zobrazenia podľa stavu dokumentu,
  • výrazoch podobných validácii.

Načítavanie dokumentov

Najvýkonnejšou funkciou CEL je načítavanie dokumentov z ľubovoľného miesta v CMS.

Načítanie jedného dokumentu

Syntax: documents.get(schemaName, identifier)

Predstavme si dokument article uložený s identifikátorom "welcome-post":

// Uložené v CMS ako: article / welcome-post
{
  "headline": "Welcome to Our Platform",
  "author": "Sarah Chen",
  "body": "We're excited to announce...",
  "tags": ["announcement", "news"]
}

Načítanie celého dokumentu:

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

Výsledok:

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

Načítanie iba nadpisu:

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

Výsledok: "Welcome to Our Platform"

Načítanie autora:

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

Výsledok: "Sarah Chen"


Používanie parametrov URL

Ak má stránka dynamické trasy, napríklad /articles/[slug], pomocou meta.params môžete získať parameter URL a načítať správny dokument.

Ak niekto navštívi /articles/welcome-post:

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

Výsledok: "Welcome to Our Platform"

Takto vytvoríte dynamické stránky – rovnaký skript CEL funguje pre každý článok a použije slug z URL.


Načítanie viacerých dokumentov

Syntax: documents.find(schemaName) alebo documents.find(schemaName, filter)

// Získať všetky krajiny
documents.find("country")

Výsledok:

[
  { "code": "us", "name": "United States", "flag": "US" },
  { "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
  { "code": "gb", "name": "United Kingdom", "flag": "GB" }
]
// Získať krajiny pomocou filtra
documents.find("country", { "where": { "code": "us" } })

Preklady

CEL podporuje načítavanie preloženého obsahu dokumentov dvoma spôsobmi: automatickým prekladom podľa lokalizácie a explicitným vyhľadaním prekladu.

Automatický preklad pomocou meta.locale

Keď je nastavené meta.locale (napríklad z parametrov trasy alebo preferencií používateľa), documents.get() automaticky zlúči preložený obsah:

// Ak je meta.locale "fr", vráti francúzsky preklad zlúčený so základným dokumentom
documents.get("greeting", "welcome").headline

Ako to funguje:

  1. Načíta základný obsah dokumentu.
  2. Ak meta.locale nie je "en" ani "en-US", vyhľadá preklad v tabuľke translations.
  3. Zlúči preložené polia so základným obsahom: { ...baseContent, ...translatedContent }.

Preložené polia teda prepíšu základné polia, zatiaľ čo nepreložené polia sa použijú zo základného dokumentu.

Explicitný preklad pomocou documents.translated()

Ak potrebujete načítať konkrétny preklad bez ohľadu na aktuálnu lokalizáciu:

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

// Vždy načítať španielsky preklad
documents.translated("greeting", "welcome", "es").headline

// Načítať preklad podľa parametra URL
documents.translated("product", meta.params.id, meta.params.lang).description

// Porovnať preklady
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Príklady z praxe

Príklad 1: Nadpis hero bloku z iného dokumentu

Máte hero-block, ktorý má zobrazovať nadpis načítaný z dokumentu article.

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

Skript CEL v poli nadpisu hero bloku:

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

Výsledok: Hero zobrazí "Build Faster, Ship Smarter".


Príklad 2: Názov krajiny podľa kódu

Vytvárate stránku /countries/[code] a chcete zobraziť úplný názov krajiny.

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

Pri návšteve /countries/us:

  • meta.params.code = "us"
  • Výsledok: "United States"

Pri návšteve /countries/sa:

  • meta.params.code = "sa"
  • Výsledok: "Saudi Arabia"

Príklad 3: Podmienený obsah podľa lokalizácie

Zobrazte rôzne nadpisy podľa lokalizácie používateľa:

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

Ak je lokalizácia "ar-SA": výsledok je "Welcome, everyone". Akákoľvek iná lokalizácia: výsledok je "Welcome".


Príklad 4: Zreťazené vyhľadávanie dokumentov

Dokument article obsahuje pole countryCode a chcete získať úplný názov krajiny.

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

Postup:

  1. documents.get("article", "us-news") vráti článok s countryCode = "us".
  2. .countryCode extrahuje "us".
  3. documents.get("country", "us") vráti dokument krajiny.
  4. .name extrahuje "United States".

Výsledok: "United States"


Príklad 5: Náhradné hodnoty

Ak dokument nemusí existovať, môžete zadať náhradnú hodnotu:

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

Alebo skontrolovať, či existuje konkrétne pole:

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

Príklad 6: Práca so zoznamami

Ak má článok štítky a chcete overiť, či obsahuje konkrétny štítok:

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

Výsledok: true, ak článok obsahuje štítok "featured".

Prvý štítok získate takto:

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

Počet štítkov:

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

Výsledok: 2.


Parametrické trasy a meta.params

Parametrické trasy sú základom dynamických lokalizovaných stránok. Keď definujete vzor trasy, napríklad /{lang}/landingPage, CMS extrahuje parametre z URL a sprístupní ich cez meta.params.

Ako fungujú parametre trás

Dynamické segmenty sa definujú syntaxou :paramName alebo {paramName}:

VzorPríklad URLExtrahované parametre
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Každý parameter trasy možno kvôli validácii prepojiť so schémou dokumentu:

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

Toto prepojenie oznámi CMS, aby:

  1. extrahoval segment lang z URL,
  2. overil ho oproti schéme language,
  3. v prípade platnosti sprístupnil celý dokument vo vyriešených parametroch.

Príklad: Vstupná stránka podľa jazyka

Konfigurácia trasy:

  • Cesta: /{lang}/landingPage
  • Vzor: /{lang}/landingPage
  • Väzby parametrov: { "lang": "language" }

Skript CEL na načítanie lokalizovaného obsahu:

documents.get("greeting", meta.params.lang).headline
URLmeta.params.langVýsledok
/ko/landingPage"ko""Welcome"
/en/landingPage"en""Welcome"
/ja/landingPage"ja""Welcome"

Pre trasy /{country}/{lang}/products môžete použiť:

// Získať názov krajiny
documents.get("country", meta.params.country).name

// Získať zoznam produktov podľa krajiny
documents.find("product", { "where": { "country": meta.params.country } })

// Kombinovaný pozdrav špecifický pre krajinu a jazyk
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name

CMS overuje parametre hierarchicky: najprv country oproti schéme country, potom lang oproti schéme language a prípadne overí, či sa jazyk nachádza v poli country.languages[].


meta.segments – prístup k surovej ceste URL

meta.segments poskytuje surovú cestu URL ako pole. Je užitočné pri pozičnom prístupe bez pomenovaných parametrov.

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

Kedy použiť meta.segments a kedy meta.params

Prípad použitiaNajlepší prístup
Pomenované parametre zo vzoru trasymeta.params.lang
Prístup podľa pozíciemeta.segments[0]
Zistenie hĺbky cestysize(meta.segments)
Kontrola, či cesta obsahuje segment"admin" in meta.segments
// Prvý segment, často kód jazyka
meta.segments[0]

// Kontrola hĺbky cesty
size(meta.segments) > 2 ? "deep" : "shallow"

// Kontrola sekcie administrácie
"admin" in meta.segments ? "admin mode" : "public mode"

// Náhradná hodnota, ak parameter nie je naviazaný
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Úplný prehľad objektu meta

Objekt meta obsahuje kontext aktuálnej požiadavky:

VlastnosťTypOpis
meta.localestringAktuálny kód lokalizácie, napr. "en-US" alebo "ar-SA"
meta.paramsRecord<string, string>Parametre trasy extrahované zo vzoru URL
meta.segmentsstring[]Cesta URL rozdelená na segmenty
meta.docIdstring | nullUUID aktuálneho dokumentu; pri novom dokumente je null
meta.titlestringNázov aktuálneho dokumentu

meta.locale

Kód lokalizácie používa formát BCP 47:

// Kontrola jazykov písaných sprava doľava
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Získanie iba časti s jazykom
meta.locale.split("-")[0]  // Nepodporované – použite meta.params.lang

meta.params

Parametre trás sú vždy reťazce. CMS ich pred vyhodnotením overí oproti naviazaným schémam:

meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"
has(meta.params.category)  // true/false

documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Surové segmenty URL ako pole:

meta.segments[0]           // Prvý segment
meta.segments[1]           // Druhý segment
size(meta.segments)        // Počet segmentov
"products" in meta.segments  // Obsahuje cesta "products"?

meta.docId

UUID aktuálneho dokumentu, užitočné pri odkazovaní na seba:

meta.docId != null ? "editing" : "creating new"
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Názov aktuálneho dokumentu:

"Editing: " + meta.title
meta.title.contains("Draft") ? "work in progress" : "published"

documents.ref() – zreťazené vyhľadávanie

Ak je schéma známa, ale identifikátor je dynamický, môžete použiť prehľadnejšiu syntax:

// Tradičný prístup
documents.get("airports", meta.params.code).name

// Použitie ref()
documents.ref("airports").get(meta.params.code).name

Oba zápisy sú rovnocenné, no ref() jasnejšie oddeľuje dynamickú časť.


Stručný prehľad

Načítavanie dokumentov

documents.get("schema", "identifier")       // Získať jeden dokument
documents.get("schema", "id").fieldName     // Získať konkrétne pole
documents.find("schema")                    // Získať všetky dokumenty
documents.find("schema", { "where": {...}}) // Filtrovaný dotaz
documents.ref("schema").get(identifier)     // Zreťazené vyhľadávanie
documents.translated("schema", "id", "fr")  // Získať s explicitnou lokalizáciou

Kontextové premenné

meta.locale          // "en-US", "ar-SA" atď.
meta.params.xyz      // Parameter URL s názvom "xyz"
meta.segments        // Cesta URL ako pole: ["articles", "intro"]
meta.segments[0]     // Prvý segment cesty
meta.docId           // ID aktuálneho dokumentu alebo null
meta.title           // Názov aktuálneho dokumentu
doc.fieldName        // Hodnota poľa aktuálneho dokumentu v kontexte editora

Operátory

// Porovnanie
==  !=  <  <=  >  >=

// Logika
&&  ||  !

// Ternárny operátor
condition ? valueIfTrue : valueIfFalse

// Príslušnosť
"value" in listOrMap

Bežné funkcie

size(list)                    // Počet položiek
size(string)                  // Dĺžka reťazca
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Kontrola existencie vlastnosti
hasProperty(obj, "key")       // Alternatívna kontrola kľúča objektu

Chybové hlásenia

Ak sa niečo pokazí, zobrazí sa jedna z týchto chýb:

ChybaVýznam
SYNTAX_ERRORPreklep v skripte, napríklad chýbajúca úvodzovka alebo nesprávny operátor
TYPE_ERRORKombinujete typy, ktoré spolu nefungujú
RUNTIME_ERRORSkript sa spustil, ale narazil na problém, napríklad nedefinovanú premennú
FETCH_LIMIT_EXCEEDEDNačítavate priveľa dokumentov; maximum je 50
TIMEOUTSkript trval príliš dlho; maximum je 5 sekúnd
AST_DEPTH_EXCEEDEDVýraz je príliš hlboko vnorený; maximálna hĺbka je 50
SCRIPT_TOO_LONGSkript prekračuje limit 5 000 znakov

Rozšíriteľnosť a budúce možnosti

Stroj CEL je navrhnutý s ohľadom na rozšíriteľnosť. Medzi plánované možnosti patria:

Plánované: integrácia servera MCP

// Budúce: volanie externých služieb cez MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

Plánované: možnosti AI

// Budúce: generovanie obsahu pomocou AI
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"])

Tieto možnosti budú pridané prostredníctvom systému registrovaných funkcií a zachovajú spätnú kompatibilitu s existujúcimi skriptmi.


Tipy

  1. Používajte automatické dopĺňanie – zadajte documents. alebo meta. a editor zobrazí dostupné možnosti.
  2. Začnite jednoducho – najprv otestujte documents.get("schema", "id"), potom pridajte .fieldName.
  3. Kontrolujte hodnotu null – ak dokument nemusí existovať, pridajte náhradnú hodnotu pomocou != null ? ... : ....
  4. Načítavajte iba potrebné údaje – každé documents.get() alebo documents.find() sa započítava do limitu 50 načítaní.
  5. Uprednostnite meta.params pred meta.segments – pomenované parametre sú overené a spoľahlivejšie.
  6. Pre voliteľné parametre používajte has() – pred prístupom overte has(meta.params.category).
  7. Pri dynamických identifikátoroch používajte documents.ref() – syntax je prehľadnejšia, keď je schéma nemenná, ale identifikátor dynamický.
  8. Na odkazy na seba používajte doc.fieldName – tak získate polia aktuálneho dokumentu vo vypočítavaných výrazoch.

Odkazy medzi dokumentmi

Táto časť opisuje pokročilé vzory prepájania dokumentov a vytvárania relačných obsahových štruktúr.

Základný vzor odkazu

Najjednoduchší prípad: jeden dokument odkazuje na iný pomocou identifikátora.

// Článok obsahuje ID autora; načítanie mena autora
documents.get("author", documents.get("article", "intro").authorId).name

Viacúrovňové reťazenie

Hlboké vzťahy môžete vytvárať reťazením viacerých vyhľadávaní:

// Letisko → krajina → región → kontinent
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Odkaz s prekladom

// Lokalizovaný názov krajiny pre letisko
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Najlepšie postupy pri odkazoch

  1. Minimalizujte hĺbku reťazenia – každá úroveň zvyšuje latenciu a počet načítaní.
  2. Ukladajte medzivýsledky do vyrovnávacej pamäte – ak rovnakú vnorenú hodnotu potrebujete dvakrát, rodičovský dokument načítajte iba raz.
  3. Používajte kontroly null – odkazy sa môžu prerušiť po odstránení dokumentov.
  4. Uprednostnite kódy pred UUID – kódy sú vo výrazoch čitateľnejšie a stabilné medzi prostrediami.
  5. Sledujte limity načítaní – zložité reťazenia môžu rýchlo dosiahnuť limit 50 načítaní.

Každé volanie documents.get(), documents.find() a documents.ref().get() sa sleduje kvôli invalidácii vyrovnávacej pamäte. Keď sa odkazovaný dokument zmení, CMS vie, ktoré výrazy CEL treba znova vyhodnotiť.


Príloha A: Úplný príklad parametrickej trasy

Tento postup vytvorí viacjazyčnú vstupnú stránku dostupnú na adrese /{lang}/landingPage.

Krok 1: Vytvorenie schémy dokumentu greeting

V administrácii CMS vytvorte vlastnú schému s názvom 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" }
  ]
}

Krok 2: Vytvorenie dokumentov greeting

Vytvorte dokument pre každý jazyk. Do polí headline, subheadline, ctaText a ctaUrl vložte lokalizovaný obsah.

Krok 3: Vytvorenie stránky

Vytvorte stránku s touto konfiguráciou:

  • Cesta/vzor: /{lang}/landingPage
  • Stav: Aktívna
  • Mapovanie dynamických segmentov: namapujte lang na komponent language
{
  "lang": "language"
}

Krok 4: Pridanie blokov so skriptami CEL

Do trasy pridajte hero blok s týmito skriptami:

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

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

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

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

Krok 5: Použitie v Next.js

Pridajte catch-all trasu. ParametricRoutePage vyrieši stránku, extrahuje meta.params z URL, vyhodnotí väzby CEL na serveri a vykreslí každý blok prostredníctvom registra.

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

Krok 6: Test trás

Navštívte tieto URL a zobrazte lokalizovaný obsah:

URLOčakávaný nadpis
/ko/landingPage환영
/en/landingPageWelcome
/ja/landingPageいらっしゃいませ

Ako prebieha vyriešenie

Pri návšteve /ko/landingPage:

  1. Zhoda trasy: CMS nájde vzor /{lang}/landingPage.
  2. Extrahovanie parametra: meta.params.lang = "ko".
  3. Validácia: CMS overí, že "ko" existuje v schéme language.
  4. Vyhodnotenie CEL: výrazy ako documents.get("greeting", meta.params.lang) načítajú kórejský obsah.
  5. Odpoveď: lokalizované bloky sa vrátia klientovi.

Príloha B: Technická referencia

Rozhranie CelMeta (TypeScript)

interface CelMeta {
  /** Aktuálny kód lokalizácie, napr. 'en-US' */
  locale: string;
  /** Parametre trasy extrahované z URL */
  params: Record<string, string>;
  /** Segmenty cesty URL */
  segments: string[];
  /** ID aktuálneho dokumentu pri úprave existujúceho dokumentu */
  docId: string | null;
  /** Názov aktuálneho dokumentu */
  title: string;
}

Algoritmus extrahovania parametrov

Funkcia extractParams spracúva cesty URL:

Vzor: /{country}/{lang}/products
Cesta: /us/en/products

Algoritmus:
1. Normalizuje obe hodnoty (odstráni koncové lomky)
2. Rozdelí ich na segmenty
3. Porovná počet segmentov
4. Pre každý pár segmentov:
   - Ak vzor začína znakom : alebo obsahuje {}, extrahuje parameter
   - Inak sa musí presne zhodovať
5. Vráti: { country: "us", lang: "en" }

Podporované formáty väzieb parametrov

// Jednoduchá väzba (na vyhľadanie používa pole "code")
{ "lang": "language" }

// Podrobná väzba (vlastné pole slug)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Priorita vyhľadávania dokumentu

Pri načítavaní pomocou documents.get(schema, identifier) sa použije tento postup:

  1. Zhoda UUID: ak je identifikátor platné UUID, vyhľadá sa podľa id.
  2. Pole code: skontroluje sa pole content.code.
  3. Pole slug: skontroluje sa pole content.slug.
  4. Zhoda názvu: skontroluje sa pole title.

To umožňuje flexibilné odkazovanie na dokumenty pomocou ľubovoľného jedinečného identifikátora.

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