profound-logoProfound CMS
⌘K
Admin
Theme
BelgelerTutorialBlogPhilosophy
BelgelerTutorialBlogPhilosophy

Hybrid

Collection of Pages with ComponentsTypes of ComponentsSetup server sent events (SSE) content refetchInstall Profound CMS as a proxyŞablon oluşturucuda komut dosyası yazmaProject ScaffoldingMedia Library

Headless

Hızlı BaşlangıçSplit Screen JSON Component Builder with LLMComponent Zod Pull

REST API

REST API OverviewgetConnect your websitegetGET /routesgetGET /routegetGET /blocksgetCEL önbelleği ile blokları getirgetGET /blocks/generatedgetGET /componentsgetGET /components/{name}getVeri kümesi şema adını algetGET /content-changes (SSE)patchPATCH /dataset/{schema_name}postGönderi çevirisipatchÇeviri yamalarıgetKullanımı alpostPOST /csvpatchPATCH /csv
All Systems Operational
Powered Byprofound-logo
Theme

Şablon oluşturucuda komut dosyası yazma

CMS'te CEL ifadeleri yazmak için pratik bir rehber.

CMS'de CEL ifadeleri yazmak için pratik bir rehber.


CEL Nasıl Çalışır

CEL (Common Expression Language), CMS'imize yerleşik, hafif bir betik dilidir. Belgelerden veri çekmenizi, URL parametrelerini okumanızı ve değerleri anında hesaplamanızı sağlar.

Bir CEL betiği çalıştırıldığında, ifade verileri okur ve hesaplanmış bir sonuç döndürür. CEL'i salt okunur bir sorgu dili olarak düşünün. Veritabanındaki hiçbir şeyi değiştiremez; yalnızca verileri okur ve sonuç döndürür. Bu nedenle CMS'in her yerinde güvenle kullanılabilir.


Yapı Taşları

Her CEL ifadesi üç nesneye erişebilir:

NesneAçıklamaÖrnek
documentsCMS'ten herhangi bir belgeyi getirirdocuments.get("country", "us")
metaGeçerli istek hakkındaki bilgiler (yerel ayar, URL parametreleri)meta.locale, meta.params.slug
schemaGeçerli belgenin alan tanımlarıschema.fields

doc ile Kendine Referans Verme

Bir belge düzenleyicisinde CEL ifadeleri yazarken, geçerli belgenin alan değerlerine doc nesnesiyle erişebilirsiniz. Bu, hesaplanan alanları ve alanlar arası referansları mümkün kılar.

// Geçerli belgenin fiyat alanına eriş
doc.price

// Geçerli belgenin alanlarından toplamı hesapla
doc.price * doc.quantity

// Geçerli belgenin durumuna göre koşul
doc.status == "published" ? doc.title : "Taslak: " + doc.title

doc nesnesi, düzenlenen belgedeki tüm alan değerlerini içerir. Şunlar için kullanışlıdır:

  • Hesaplanan alanlar (ör. doc.price * doc.quantity)
  • Belge durumuna dayalı koşullu görüntüleme mantığı
  • Doğrulama tarzı ifadeler

Belgeleri Getirme

CEL'in en güçlü özelliği, CMS'in herhangi bir yerinden belge getirebilmesidir.

Tek Bir Belgeyi Getirme

Söz dizimi: documents.get(schemaName, identifier)

welcome-post tanımlayıcısıyla kaydedilmiş bir article belgeniz olduğunu varsayalım:

{
  "headline": "Platformumuza Hoş Geldiniz",
  "author": "Sarah Chen",
  "body": "Duyurmaktan mutluluk duyuyoruz...",
  "tags": ["duyuru", "haber"]
}

Belgenin tamamını getirmek için:

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

Yalnızca başlığı getirmek için:

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

Sonuç: "Platformumuza Hoş Geldiniz"

Yazarı getirmek için:

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

Sonuç: "Sarah Chen"


URL Parametrelerini Kullanma

Sayfanızda /articles/[slug] gibi dinamik rotalar olduğunda, URL parametresini almak ve doğru belgeyi getirmek için meta.params kullanabilirsiniz.

/articles/welcome-post adresi ziyaret edildiğinde:

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

Sonuç: "Platformumuza Hoş Geldiniz"

Dinamik sayfalar bu şekilde oluşturulur. Aynı CEL betiği, URL'deki slug değerini kullanarak tüm makalelerde çalışır.


Birden Fazla Belgeyi Getirme

Söz dizimi: documents.find(schemaName) veya documents.find(schemaName, filter)

// Tüm ülkeleri getir
documents.find("country")
// Filtreyle ülkeleri getir
documents.find("country", { "where": { "code": "us" } })

Filtreler where koşulları kullanır ve sonuç olarak belge dizisi döndürür.


Çeviriler

CEL, çevrilmiş belge içeriğini iki şekilde getirir: yerel ayara dayalı otomatik çeviri ve açık çeviri araması.

meta.locale ile Otomatik Çeviri

meta.locale ayarlandığında (örneğin rota parametrelerinden veya kullanıcı tercihlerinden), documents.get() çevrilmiş içeriği otomatik olarak birleştirir:

// meta.locale "fr" ise, temel belgeyle birleştirilmiş Fransızca çeviriyi döndürür
documents.get("greeting", "welcome").headline

Çalışma adımları:

  1. Temel belge içeriği getirilir.
  2. meta.locale, en veya en-US değilse translations tablosunda çeviri aranır.
  3. Çevrilmiş alanlar temel içeriğin üzerine birleştirilir: { ...baseContent, ...translatedContent }

Böylece çevrilmiş alanlar temel alanların üzerine yazılır; çevrilmemiş alanlar ise temel belgeden alınır.

documents.translated() ile Açık Çeviri

Geçerli yerel ayardan bağımsız olarak belirli bir çeviriyi almak için:

Söz dizimi: documents.translated(schemaName, identifier, locale)

// Her zaman İspanyolca çeviriyi getir
documents.translated("greeting", "welcome", "es").headline

// URL parametresine göre çeviriyi getir
documents.translated("product", meta.params.id, meta.params.lang).description

// Çevirileri karşılaştır
documents.translated("article", "intro", "en").title + " / " + documents.translated("article", "intro", "fr").title

Eksik çeviriler için null kontrolü ve koşullu geri dönüş kullanabilirsiniz.


Gerçek Dünya Örnekleri

Örnek 1: Başka Bir Belgeden Hero Bloğu Başlığı

hero-block bileşeninin, article belgesinden alınan bir başlığı göstermesi gerekiyorsa:

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

Sonuç: Hero, "Daha Hızlı Oluşturun, Daha Akıllıca Yayınlayın" metnini gösterir.

Örnek 2: Koddan Ülke Adı

/countries/[code] adresinde tam ülke adını göstermek için:

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

/countries/us ziyaret edildiğinde meta.params.code değeri "us" olur ve sonuç "Amerika Birleşik Devletleri" şeklindedir.

Örnek 3: Yerel Ayara Göre Koşullu İçerik

meta.locale == "ar-SA" ? "Herkese hoş geldiniz" : "Hoş geldiniz"

Örnek 4: Zincirleme Belge Aramaları

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

Önce makale getirilir, countryCode alanı çıkarılır, ardından ilgili ülke getirilerek name alanı alınır.

Örnek 5: Geri Dönüş Değerleri

documents.get("article", meta.params.slug) != null
  ? documents.get("article", meta.params.slug).headline
  : "Makale Bulunamadı"

Belirli bir alanı kontrol etmek için de aynı koşullu yapı kullanılabilir.

Örnek 6: Listelerle Çalışma

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

Makalenin etiketi varsa true döner.

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

İlk ifade ilk etiketi, ikinci ifade etiket sayısını döndürür.


Parametreli Rotalar ve meta.params

Parametreli rotalar dinamik ve yerelleştirilmiş sayfalar oluşturmanın temelidir. /{lang}/landingPage gibi bir rota tanımladığınızda CMS, URL'deki parametreleri çıkarır ve meta.params üzerinden kullanılabilir hale getirir.

Rota Parametreleri Nasıl Çalışır

Dinamik bölümler :paramName veya {paramName} söz dizimiyle tanımlanır:

DesenÖrnek URLÇıkarılan Parametreler
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Parametreler doğrulama amacıyla belge şemalarına bağlanabilir:

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

Bu bağlantı CMS'e şunları söyler:

  1. URL'deki lang bölümünü çıkar.
  2. language şemasına göre doğrula.
  3. Geçerliyse, çözümlenen parametrelerde tüm belgeyi kullanılabilir yap.

Dil Tabanlı Açılış Sayfası

Yerelleştirilmiş içeriği getirmek için:

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

/ko/landingPage, /en/landingPage ve /ja/landingPage adresleri, sırasıyla ko, en ve ja belgelerinin başlığını getirir.

Ülke ve Dil Rotaları

/{country}/{lang}/products gibi rotalar için:

{
  "pattern": "/{country}/{lang}/products",
  "param_bindings": {
    "country": "country",
    "lang": "language"
  }
}
// Ülke adını getir
documents.get("country", meta.params.country).name

// Ülkeye göre yerelleştirilmiş ürün listesini getir
documents.find("product", { "where": { "country": meta.params.country } })

// Kullanıcının dilinde ülkeye özel selamlama
documents.get("greeting", meta.params.lang).headline + " - " + documents.get("country", meta.params.country).name

CMS parametreleri hiyerarşik olarak doğrular: önce ülke, sonra dil ve isteğe bağlı olarak dilin ülkenin languages[] dizisinde bulunup bulunmadığı kontrol edilir.


meta.segments - Ham URL Yoluna Erişim

meta.segments, ham URL yolunu bir dizi olarak sunar:

URL yolumeta.segments
/articles/tech/ai-news["articles", "tech", "ai-news"]
/ko/landingPage["ko", "landingPage"]
/[]

meta.segments ve meta.params Ne Zaman Kullanılmalı

KullanımEn iyi yaklaşım
Rota desenindeki adlandırılmış parametrelermeta.params.lang
Konuma dayalı erişimmeta.segments[0]
Yol derinliğini almasize(meta.segments)
Yolun bir bölüm içerip içermediğini kontrol etme"admin" in meta.segments
// İlk bölümü al
meta.segments[0]

// Yol derinliğini kontrol et
size(meta.segments) > 2 ? "derin" : "sığ"

// Yönetici bölümünde olup olmadığını kontrol et
"admin" in meta.segments ? "yönetici modu" : "genel mod"

// Parametre bağlı değilse bölümü kullan
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Eksiksiz meta Nesnesi Başvurusu

meta nesnesi geçerli istek hakkındaki tüm bağlamı içerir:

ÖzellikTürAçıklama
meta.localestringGeçerli yerel ayar kodu (ör. "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>URL deseninden çıkarılan rota parametreleri
meta.segmentsstring[]Bölümlere ayrılmış URL yolu
meta.docIdstring \| nullGeçerli belge UUID'si; yeni belgelerde null
meta.titlestringGeçerli belgenin başlığı

meta.locale

Yerel ayar kodu BCP 47 biçimini izler:

// RTL dillerini kontrol et
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Dil bölümünü almak için rota parametresini kullan
meta.params.lang

meta.params

Rota parametreleri her zaman dizedir:

meta.params.lang
meta.params.country
meta.params.slug

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

meta.segments

meta.segments[0]
meta.segments[1]
size(meta.segments)
"products" in meta.segments

meta.docId

meta.docId != null ? "düzenleniyor" : "yeni oluşturuluyor"
meta.docId != null ? documents.get("article", meta.docId).status : "taslak"

meta.title

"Düzenleniyor: " + meta.title
meta.title.contains("Taslak") ? "devam eden çalışma" : "yayında"

documents.ref() - Zincirleme Aramalar

Şema biliniyor ancak tanımlayıcı dinamikse daha temiz bir söz dizimi kullanabilirsiniz:

// Geleneksel yaklaşım
documents.get("airports", meta.params.code).name

// ref() kullanımı
documents.ref("airports").get(meta.params.code).name

İki yaklaşım eşdeğerdir; ancak ref() dinamik bölümü daha anlaşılır kılar.


Hızlı Başvuru

Belge Getirme

documents.get("schema", "identifier")
documents.get("schema", "id").fieldName
documents.find("schema")
documents.find("schema", { "where": {...}})
documents.ref("schema").get(identifier)
documents.translated("schema", "id", "fr")

Bağlam Değişkenleri

meta.locale
meta.params.xyz
meta.segments
meta.segments[0]
meta.docId
meta.title
doc.fieldName

Operatörler

==  !=  <  <=  >  >=
&&  ||  !
condition ? valueIfTrue : valueIfFalse
"value" in listOrMap

Yaygın İşlevler

size(list)
size(string)
"text".startsWith("te")
"text".endsWith("xt")
"text".contains("ex")
has(object.property)
hasProperty(obj, "key")

Hata Mesajları

HataAnlamı
SYNTAX_ERRORBetikte yazım hatası var
TYPE_ERRORBirbiriyle uyumsuz türler kullanılıyor
RUNTIME_ERRORBetik çalışırken bir sorun oluştu
FETCH_LIMIT_EXCEEDEDÇok fazla belge getiriliyor (en fazla 50)
TIMEOUTBetik çok uzun sürdü (en fazla 5 saniye)
AST_DEPTH_EXCEEDEDİfade çok derin iç içe geçmiş (en fazla 50)
SCRIPT_TOO_LONGBetik 5000 karakter sınırını aşıyor

Genişletilebilirlik ve Gelecekteki Yetenekler

CEL motoru genişletilebilir olacak şekilde tasarlanmıştır. Planlanan yetenekler arasında MCP sunucusu entegrasyonu ve yapay zekâ özellikleri bulunur:

// Gelecekte: MCP aracılığıyla harici hizmetleri çağır
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

// Gelecekte: Yapay zekâ destekli içerik üretimi
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"])

Bu yetenekler, mevcut betiklerle geriye dönük uyumluluk korunarak kayıtlı işlev sistemi üzerinden eklenecektir.


İpuçları

  1. Otomatik tamamlamayı kullanın - documents. veya meta. yazdığınızda kullanılabilir seçenekler gösterilir.
  2. Basit başlayın - Önce documents.get("schema", "id") ile test edin, sonra .fieldName ekleyin.
  3. Null değerleri kontrol edin - Belge mevcut olmayabilirse != null ? ... : ... ile geri dönüş ekleyin.
  4. Gereğinden fazla veri getirmeyin - Her documents.get() veya documents.find() çağrısı 50 getirme sınırına dahildir.
  5. meta.segments yerine meta.params kullanmayı tercih edin - Adlandırılmış parametreler doğrulanır ve daha güvenilirdir.
  6. İsteğe bağlı parametreler için has() kullanın.
  7. Dinamik tanımlayıcılar için documents.ref() kullanın.
  8. Kendine referanslar için doc.fieldName kullanın.

Belgeden Belgeye Referanslar

Bu bölüm, belgeleri birbirine bağlamak ve ilişkisel içerik yapıları oluşturmak için gelişmiş kalıpları açıklar.

Temel Referans Kalıbı

Bir belgenin diğerine tanımlayıcı üzerinden referans vermesinin en basit biçimi:

// Makale yazar kimliğini saklar; yazarın adını getir
documents.get("author", documents.get("article", "intro").authorId).name

documents.ref() ile Zincirleme Aramalar

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

Çok Düzeyli Referans Zincirleri

// Havaalanı → Ülke → Bölge → Kıta
documents.get("continent",
  documents.get("region",
    documents.get("country",
      documents.get("airport", meta.params.code).countryCode
    ).regionCode
  ).continentCode
).name

Çevirili Referans

// Bir havaalanı için yerelleştirilmiş ülke adını getir
documents.translated("country",
  documents.get("airport", meta.params.code).countryCode,
  meta.params.lang
).name

Kullanım Alanına Göre Referans Kalıpları

Belgeler UUID veya anlamsal kodlarla birbirlerine referans verebilir. Geçerli belgenin değerlerine göre ilişkili belgeleri getirmek için doc kullanılabilir:

// Ürün belgesinde ilişkili kategori ayrıntılarını getir
documents.get("category", doc.categoryId).description

// Ürünün menşe ülkesine göre kargo ücretini hesapla
documents.get("shipping-rates", doc.originCountry).baseRate * doc.weight

Polimorfik referanslarda kaynak şemasına göre koşullu arama yapılabilir:

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

Bağımlılık Takibi

Her documents.get(), documents.find() ve documents.ref().get() çağrısı önbellek geçersizleştirme amacıyla izlenir. Referans verilen belge değiştiğinde CMS, hangi CEL ifadelerinin yeniden değerlendirilmesi gerektiğini bilir.

  • get: schema:identifier - Belirli belge bağımlılığı
  • ref: schema:identifier - Zincirli söz dizimiyle get ile aynı
  • query: schema:* - Şema düzeyinde bağımlılık

Referanslar için En İyi Uygulamalar

  1. Zincir derinliğini azaltın.
  2. Ara sonuçları önbelleğe alın.
  3. Null kontrolleri kullanın.
  4. UUID yerine okunabilir kodları tercih edin.
  5. 50 belge getirme sınırını göz önünde bulundurun.

Ek A: Eksiksiz Parametreli Rota Örneği

Bu örnek, /{lang}/landingPage adresinden erişilebilen çok dilli bir açılış sayfası oluşturur.

1. Selamlama Belgesi Şemasını Oluşturun

CMS yönetiminde greeting adında özel bir şema oluşturun:

{
  "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" }
  ]
}

2. Selamlama Belgelerini Oluşturun

Her dil için belgeler oluşturun. Örneğin greeting/ko, greeting/en ve greeting/ja belgeleri code, headline, subheadline, ctaText ve ctaUrl alanlarını içerir.

3. Sayfayı Oluşturun

  • Yol/Desen: /{lang}/landingPage
  • Durum: Yayında
  • Dinamik Bölüm Eşlemeleri: lang → language bileşeni
{
  "lang": "language"
}

4. CEL Betikleriyle Bloklar Ekleyin

// Başlık
documents.get("greeting", meta.params.lang).headline

// Alt başlık
documents.get("greeting", meta.params.lang).subheadline

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

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

5. Next.js'te Kullanma

Catch-all rota ekleyin. ParametricRoutePage sayfayı çözümler, URL'den meta.params değerlerini çıkarır, CEL bağlantılarını sunucu tarafında değerlendirir ve her bloğu kayıt defteriniz üzerinden oluşturur.

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

6. Rotaları Test Etme

URLBeklenen Başlık
/ko/landingPage환영
/en/landingPageHoş geldiniz
/ja/landingPageいらっしゃいませ

Çözümleme Nasıl Çalışır

Kullanıcı /ko/landingPage adresini ziyaret ettiğinde:

  1. Rota eşleştirme: CMS /{lang}/landingPage desenini eşleştirir.
  2. Parametre çıkarma: meta.params.lang = "ko" olur.
  3. Doğrulama: CMS, "ko" değerinin language şemasında bulunduğunu doğrular.
  4. CEL değerlendirmesi: documents.get("greeting", meta.params.lang) Korece içeriğe çözülür.
  5. Yanıt: Yerelleştirilmiş bloklar istemciye döndürülür.

Ek B: Teknik Başvuru

CelMeta Arayüzü (TypeScript)

interface CelMeta {
  /** Geçerli yerel ayar kodu (ör. 'en-US') */
  locale: string;
  /** URL'den çıkarılan rota parametreleri */
  params: Record<string, string>;
  /** URL yol bölümleri */
  segments: string[];
  /** Geçerli belge kimliği */
  docId: string | null;
  /** Geçerli belge başlığı */
  title: string;
}

Parametre Çıkarma Algoritması

extractParams işlevi URL yollarını işler:

Desen: /{country}/{lang}/products
Yol:    /us/en/products

Algoritma:
1. Her ikisini normalleştir (sondaki eğik çizgileri kaldır)
2. Bölümlere ayır
3. Bölüm sayılarını karşılaştır
4. Her bölüm çifti için:
   - Desen : veya {} ile başlıyorsa parametre olarak çıkar
   - Aksi halde tam eşleşme gerekir
5. Şunu döndür: { country: "us", lang: "en" }

Desteklenen Parametre Bağlama Biçimleri

// Basit bağlama
{ "lang": "language" }

// Ayrıntılı bağlama
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }
}

Belge Arama Önceliği

documents.get(schema, identifier) ile arama yapılırken:

  1. UUID eşleşmesi: Tanımlayıcı geçerli bir UUID ise id ile aranır.
  2. Kod alanı: content.code alanı kontrol edilir.
  3. Slug alanı: content.slug alanı kontrol edilir.
  4. Başlık eşleşmesi: title alanı kontrol edilir.

Bu sayede belgeler benzersiz olan herhangi bir tanımlayıcıyla esnek biçimde referanslanabilir.

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