All Systems Operational
Powered By
profound-logo
profound-logoProfound CMS
⌘K
Admin

Skryptowanie W Kreatorze Szablonów

Praktyczny przewodnik po pisaniu wyrażeń CEL w CMS.

Continue Reading
Previous‹Renderowanie statyczne z obsługą trybu edycjiNextCreate Profound Next›

Praktyczny przewodnik po pisaniu wyrażeń CEL w CMS.


Jak działa CEL

CEL (Common Expression Language) to lekki język skryptowy wbudowany w nasz CMS. Umożliwia pisanie dynamicznych wyrażeń, które mogą pobierać dane z dokumentów, odczytywać parametry URL i obliczać wartości w locie.

Tak wygląda działanie skryptu CEL w czasie wykonywania:

Twój skrypt                    Mechanizm                      Wynik
    |                              |                              |
    v                              v                              v
documents.get("article", "intro") --> Pobiera z bazy danych --> { headline: "Welcome", body: "..." }
         .headline                --> Wyodrębnia pole        --> "Welcome"

Traktuj CEL jak język zapytań tylko do odczytu. Nie może zmieniać niczego w bazie danych — jedynie odczytuje dane i zwraca wynik obliczeń. Dzięki temu można go bezpiecznie używać w dowolnym miejscu CMS.


Elementy składowe

Każde wyrażenie CEL ma dostęp do trzech elementów:

ObiektCo to jestPrzykład
documentsPobierz dowolny dokument z CMSdocuments.get("country", "us")
metaInformacje o bieżącym żądaniu (lokalizacja, parametry URL)meta.locale, meta.params.slug
schemaDefinicje pól bieżącego dokumentuschema.fields

Pobieranie dokumentów

Najpotężniejszą funkcją CEL jest pobieranie dokumentów z dowolnego miejsca w CMS.

Pobieranie pojedynczego dokumentu

Składnia: documents.get(schemaName, identifier)

Załóżmy, że masz dokument article zapisany z identyfikatorem "welcome-post":

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

Aby pobrać cały dokument:

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

Zwraca:

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

Aby pobrać tylko nagłówek:

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

Zwraca: "Welcome to Our Platform"

Aby pobrać autora:

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

Zwraca: "Sarah Chen"


Używanie parametrów URL

Gdy Twoja strona ma dynamiczne trasy (na przykład /articles/[slug]), możesz użyć meta.params, aby pobrać parametr z adresu URL i załadować właściwy dokument.

Jeśli ktoś odwiedzi /articles/welcome-post:

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

Zwraca: "Welcome to Our Platform"

Tak budujesz dynamiczne strony — ten sam skrypt CEL działa dla dowolnego artykułu, wykorzystując slug z adresu URL.


Pobieranie wielu dokumentów

Składnia: documents.find(schemaName) lub documents.find(schemaName, filter)

// Pobierz wszystkie kraje
documents.find("country")

Zwraca:

[
  { "code": "us", "name": "United States", "flag": "US" },
  { "code": "sa", "name": "Saudi Arabia", "flag": "SA" },
  { "code": "gb", "name": "United Kingdom", "flag": "GB" }

// Pobierz kraje z filtrem
documents.find("country", { "where": { "code": "us" } })

Zwraca:

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

Przykłady z praktyki

Przykład 1: Tytuł bloku Hero z innego dokumentu

Masz hero-block, który powinien wyświetlać nagłówek pobrany z dokumentu article.

Twój dokument article (identyfikator: "homepage-hero"):

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

Skrypt CEL w polu tytułu bloku hero:

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

Wynik: Hero wyświetla "Build Faster, Ship Smarter"


Przykład 2: Nazwa kraju na podstawie kodu

Budujesz stronę pod /countries/[code] i chcesz wyświetlić pełną nazwę kraju.

Twoje dokumenty 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"

Skrypt CEL:

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

Gdy ktoś odwiedzi /countries/us:

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

Gdy ktoś odwiedzi /countries/sa:

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

Przykład 3: Treść warunkowa w zależności od ustawień regionalnych

Wyświetlaj różne nagłówki w zależności od ustawień regionalnych użytkownika.

meta.locale == "ar-SA" ? "مرحبا بكم" : "Welcome"

Jeśli ustawienie regionalne to "ar-SA": Zwraca "مرحبا بكم" Jeśli ustawienie regionalne jest inne: Zwraca "Welcome"


Przykład 4: Łańcuchowe wyszukiwanie dokumentów

Twój article ma pole countryCode, a Ty chcesz pobrać pełną nazwę kraju.

Dokument article:

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

Skrypt CEL:

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

Co się dzieje:

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

Wynik: "United States"


Przykład 5: Wartości domyślne

Jeśli dokument może nie istnieć, możesz podać wartość zapasową:

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

Albo sprawdź, czy konkretne pole istnieje:

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

Przykład 6: Praca z listami

Twój artykuł ma tagi i chcesz sprawdzić, czy istnieje konkretny tag:

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

Zwraca: true, jeśli artykuł ma tag "featured"

Pobierz pierwszy tag:

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

Zwraca: "announcement" (pierwszy tag)

Policz tagi:

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

Zwraca: 2 (liczba tagów)


Trasy parametryczne i meta.params

Trasy parametryczne są kluczem do budowania dynamicznych, zlokalizowanych stron. Gdy zdefiniujesz wzorzec trasy, taki jak /{lang}/landingPage, CMS wyodrębnia parametry z adresu URL i udostępnia je przez meta.params.

Jak działają parametry tras

Definicja wzorca trasy: Trasy używają składni :paramName lub {paramName} do definiowania dynamicznych segmentów:

WzorzecPrzykładowy URLWyodrębnione parametry
/:lang/landingPage/ko/landingPage{ lang: "ko" }
/{country}/{lang}/products/us/en/products{ country: "us", lang: "en" }
/articles/:slug/articles/welcome-post{ slug: "welcome-post" }

Powiązania parametrów: Każdy parametr trasy można powiązać ze schematem dokumentu w celu walidacji:

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

To powiązanie informuje CMS, że:

  1. Wyodrębnij segment lang z adresu URL
  2. Zweryfikuj go względem schematu language (szuka dokumentu, w którym content.code się zgadza)
  3. Jeśli jest poprawny, udostępnij pełny dokument w rozstrzygniętych parametrach

Przykład: strona docelowa zależna od języka

Konfiguracja trasy:

  • Ścieżka: /{lang}/landingPage
  • Wzorzec: /{lang}/landingPage
  • Powiązania parametrów: { "lang": "language" }

Twoje dokumenty greeting:

// greeting / ko
{ "code": "ko", "headline": "환영합니다", "subheadline": "우리 플랫폼에 오신 것을 환영합니다" }

// greeting / en
{ "code": "en", "headline": "Welcome", "subheadline": "Welcome to our platform" }

// greeting / ja
{ "code": "ja", "headline"

Skrypt CEL do pobrania zlokalizowanej treści:

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

Jak to się rozwiązuje:

URLmeta.params.langWynik
/ko/landingPage"ko""환영합니다"
/en/landingPage"en""Welcome"
/ja/landingPage"ja""ようこそ"

Zaawansowany wzorzec: trasy kraj + język

Dla tras takich jak /{country}/{lang}/products:

Konfiguracja trasy:

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

Skrypty CEL:

// Pobierz nazwę kraju
documents.get("country", meta.params.country).name

// Pobierz zlokalizowaną listę produktów na podstawie kraju
documents.find("product", { "where": { "country": meta.params.country } })

// Połączone: pokaż powitanie specyficzne dla kraju w języku użytkownika
documents.get("greeting", meta.params.lang).headline + " from " + documents.get("country", meta.params.country).name

Kaskada walidacji: CMS weryfikuje parametry hierarchicznie. Dla tras /{country}/{lang}:

  1. Weryfikuje parametr country względem schematu country
  2. Weryfikuje parametr lang względem schematu language
  3. Opcjonalnie sprawdza, czy lang znajduje się w tablicy country.languages[] (walidacja hierarchiczna)

meta.segments – dostęp do surowej ścieżki URL

meta.segments udostępnia surową ścieżkę URL jako tablicę, co jest przydatne, gdy potrzebujesz dostępu do segmentów po indeksie bez nazwanych parametrów.

Jak to działa:

Ścieżka URLmeta.segments
/articles/tech/ai-news["articles", "tech", "ai-news"]
/ko/landingPage["ko", "landingPage"]
/us/en/products/featured["us", "en", "products", "featured"]
/[]

Kiedy używać meta.segments, a kiedy meta.params

ZastosowanieNajlepsze podejście
Nazwane parametry z wzorca trasymeta.params.lang
Dostęp oparty na pozycjimeta.segments[0]
Sprawdzenie głębokości ścieżkisize(meta.segments)
Sprawdzenie, czy ścieżka zawiera segment"admin" in meta.segments

Przykłady z meta.segments

// Pobierz pierwszy segment (często kod języka)
meta.segments[0]

// Sprawdź głębokość ścieżki
size(meta.segments) > 2 ? "deep" : "shallow"

// Sprawdź, czy jesteśmy w sekcji administracyjnej
"admin" in meta.segments ? "admin mode" : "public mode"

// Fallback: użyj segmentu, jeśli parametr nie jest powiązany
has(meta.params.lang) ? meta.params.lang : meta.segments[0]

Pełna referencja obiektu meta

Obiekt meta zawiera cały kontekst dotyczący bieżącego żądania:

WłaściwośćTypOpis
meta.localestringAktualny kod ustawień regionalnych (np. "en-US", "ko-KR", "ar-SA")
meta.paramsRecord<string, string>Parametry trasy wyodrębnione z wzorca URL
meta.segmentsstring[]Ścieżka URL podzielona na segmenty
meta.docIdstring \\ | nullBieżący UUID dokumentu (null dla nowych dokumentów)
meta.titlestringAktualny tytuł dokumentu

meta.locale

Kod ustawień regionalnych stosuje format BCP 47 (język-region):

// Sprawdź ustawienia regionalne dla języków RTL
meta.locale == "ar-SA" || meta.locale == "he-IL" ? "rtl" : "ltr"

// Pobierz tylko część językową
meta.locale.split("-")[0]  // Nieobsługiwane – użyj meta.params.lang zamiast tego

meta.params

Parametry tras są zawsze łańcuchami znaków. CMS weryfikuje je względem powiązanych schematów przed ewaluacją:

// Dostęp do nazwanego parametru
meta.params.lang           // "ko"
meta.params.country        // "us"
meta.params.slug           // "welcome-post"

// Sprawdź, czy parametr istnieje
has(meta.params.category)  // true/false

// Użyj przy pobieraniu dokumentu
documents.get("greeting", meta.params.lang)
documents.ref("airports").get(meta.params.code)

meta.segments

Surowe segmenty adresu URL jako tablica:

// Dostęp po indeksie (0-based)
meta.segments[0]           // Pierwszy segment
meta.segments[1]           // Drugi segment

// Sprawdź długość
size(meta.segments)        // Liczba segmentów

// Sprawdź, czy segment istnieje
"products" in meta.segments  // Czy ścieżka zawiera "products"?

meta.docId

Bieżący UUID dokumentu, przydatny dla skryptów odnoszących się do siebie samych:

// Dostępny tylko podczas edycji istniejących dokumentów
meta.docId != null ? "editing" : "creating new"

// Użyj w logice warunkowej
meta.docId != null ? documents.get("article", meta.docId).status : "draft"

meta.title

Bieżący tytuł dokumentu:

// Użyj do wyświetlania
"Editing: " + meta.title

// Warunek oparty na tytule
meta.title.contains("Draft") ? "work in progress" : "published"

documents.ref() – łańcuchowe wyszukiwanie

Dla bardziej przejrzystej składni, gdy schemat jest znany, ale identyfikator jest dynamiczny:

// Tradycyjne podejście
documents.get("airports", meta.params.code).name

// Użycie ref() – schemat oddzielony od dynamicznego identyfikatora
documents.ref("airports").get(meta.params.code).name

Obie metody są równoważne, ale ref() sprawia, że część dynamiczna jest bardziej przejrzysta.


Szybka ściągawka

Pobieranie dokumentów

documents.get("schema", "identifier")       // Pobierz jeden dokument
documents.get("schema", "id").fieldName     // Pobierz konkretne pole
documents.find("schema")                    // Pobierz wszystkie dokumenty
documents.find("schema", { "where": {...}}) // Zapytanie z filtrem
documents.ref("schema").get(identifier)     // Łańcuchowe wyszukiwanie

Zmienne kontekstowe

meta.locale          // "en-US", "ar-SA" itp.
meta.params.xyz      // Parametr URL o nazwie "xyz"
meta.segments        // Ścieżka URL jako tablica: ["articles", "intro"]
meta.segments[0]     // Pierwszy segment ścieżki
meta.docId           // ID bieżącego dokumentu (lub null)
meta.title           // Tytuł bieżącego dokumentu

Operatory

// Porównania
==  !=  <  <=  >  >=

// Logika
&&  ||  !

// Operator trójargumentowy (if-else)
condition ? valueIfTrue : valueIfFalse

// Przynależność
"value" in listOrMap

Popularne funkcje

size(list)                    // Liczba elementów
size(string)                  // Długość łańcucha
"text".startsWith("te")       // true
"text".endsWith("xt")         // true
"text".contains("ex")         // true
has(object.property)          // Sprawdź, czy właściwość istnieje

Komunikaty błędów

Jeśli coś pójdzie nie tak, zobaczysz jeden z tych komunikatów:

BłądCo oznacza
SYNTAX_ERRORLiterówka w skrypcie (brakujący cudzysłów, zły operator)
TYPE_ERRORMieszasz typy, które do siebie nie pasują
RUNTIME_ERRORSkrypt się uruchomił, ale napotkał problem (niezdefiniowana zmienna)
FETCH_LIMIT_EXCEEDEDPobierasz zbyt wiele dokumentów (maksymalnie 50)
TIMEOUTSkrypt trwał zbyt długo (maksymalnie 5 sekund)
AST_DEPTH_EXCEEDEDWyrażenie jest zbyt zagnieżdżone (maksymalna głębokość: 50)
SCRIPT_TOO_LONGSkrypt przekracza limit 5000 znaków

Rozszerzalność i przyszłe możliwości

Silnik CEL został zaprojektowany z myślą o rozszerzalności. Przyszłe możliwości obejmują:

Planowane: integracja z serwerem MCP

// Przyszłość: wywoływanie usług zewnętrznych przez MCP
mcp.translate(meta.params.text, "en", meta.params.lang)
mcp.analyze(documents.get("article", meta.params.id).body)

Planowane: możliwości AI

// Przyszłość: generowanie treści wspierane przez 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"])

Te możliwości zostaną dodane poprzez system zarejestrowanych funkcji, zachowując kompatybilność wsteczną z istniejącymi skryptami.


Wskazówki

  1. Korzystaj z podpowiedzi – wpisz documents. lub meta. i edytor pokaże dostępne opcje
  2. Zacznij od prostych rzeczy – przetestuj documents.get("schema", "id"), a potem dodaj .fieldName
  3. Sprawdzaj null – jeśli dokument może nie istnieć, dodaj wartość zapasową z != null ? ... : ...
  4. Nie pobieraj za dużo – każde documents.get() lub documents.find() liczy się do limitu 50 pobrań
  5. Preferuj meta.params zamiast meta.segments – nazwane parametry są weryfikowane i bardziej niezawodne
  6. Używaj has() dla opcjonalnych parametrów – sprawdź has(meta.params.category) przed użyciem
  7. Stosuj documents.ref() przy dynamicznych identyfikatorach – czytelniejsza składnia, gdy schemat jest stały, a identyfikator zmienny

Dodatek A: Kompletny przykład trasy parametrycznej

Ten przewodnik krok po kroku tworzy wielojęzyczną stronę docelową dostępną pod /{lang}/landingPage.

Krok 1: Utwórz schemat dokumentu greeting

W panelu administracyjnym CMS utwórz niestandardowy schemat o nazwie greeting:

{
  "name": "greeting",
  "fields": [
    { "name": "code", "type": "string", "required": true },
    { "name": "headline", "type": "string", "required": true },
    { "name": "subheadline"

Krok 2: Utwórz dokumenty greeting

Utwórz dokumenty dla każdego języka:

Dokument: greeting / ko

{
  "code": "ko",
  "headline": "환영합니다",
  "subheadline": "우리 플랫폼에 오신 것을 환영합니다",
  "ctaText": "시작하기",
  "ctaUrl": "/ko/get-started"
}

Dokument: greeting / en

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

Dokument: greeting / ja

{
  "code": "ja",
  "headline": "ようこそ",
  "subheadline": "私たちのプラットフォームへようこそ",
  "ctaText": "始める",
  "ctaUrl": "/ja/get-started"
}

Krok 3: Utwórz trasę

Utwórz trasę z następującą konfiguracją:

  • Ścieżka: /{lang}/landingPage
  • Wzorzec: /{lang}/landingPage
  • Stan: Live
  • Powiązania parametrów:
  {
    "lang": "language"
  }

Krok 4: Dodaj bloki ze skryptami CEL

Dodaj blok hero do trasy z następującymi skryptami CEL dla każdego pola:

Pole nagłówka:

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

Pole podtytułu:

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

Pole tekstu CTA:

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

Pole adresu URL CTA:

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

Krok 5: Obsłuż w Next.js

Utwórz trasę catch-all w aplikacji Next.js:

// app/[...slug]/page.tsx
import { getCmsClient } from '@repo/renderer';

interface PageProps {
  params: { slug: string[] };
}

export default async function Page({ params }: PageProps) {

Krok 6: Przetestuj trasy

Odwiedź te adresy URL, aby zobaczyć zlokalizowaną treść:

URLOczekiwany nagłówek
/ko/landingPage환영합니다
/en/landingPageWelcome
/ja/landingPageようこそ

Jak przebiega rozwiązywanie

Gdy użytkownik odwiedza /ko/landingPage:

  1. Dopasowanie trasy: CMS dopasowuje wzorzec /{lang}/landingPage
  2. Wyodrębnianie parametrów: meta.params.lang = "ko"
  3. Walidacja: CMS sprawdza, czy "ko" istnieje w schemacie language
  4. Ewaluacja CEL: Skrypty takie jak documents.get("greeting", meta.params.lang) zwracają koreańską treść
  5. Odpowiedź: Zlokalizowane bloki są zwracane do klienta

Dodatek B: Referencja techniczna

Interfejs CelMeta (TypeScript)

interface CelMeta {
  /** Aktualny kod ustawień regionalnych (np. 'en-US') */
  locale: string;
  /** Parametry trasy wyodrębnione z adresu URL */
  params: Record<string, string>;
  /** Segmenty ścieżki URL */
  segments: string[];
  /** ID bieżącego dokumentu (jeśli edytujesz istniejący dokument) */

Algorytm wyodrębniania parametrów

Funkcja extractParams przetwarza ścieżki URL:

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

Algorithm:
1. Ujednolić oba (usunąć końcowe ukośniki)
2. Podzielić na segmenty: ["us", "en", "products"] i ["{country}", "{lang}", "products"]

Obsługiwane formaty powiązania parametrów

// Proste powiązanie (używa pola "code" do wyszukiwania)
{ "lang": "language" }

// Szczegółowe powiązanie (niestandardowe pole slug)
{
  "lang": {
    "schemaName": "language",
    "slugField": "code"
  },
  "slug": {
    "schemaName": "article",
    "slugField": "slug"
  }

Priorytet wyszukiwania dokumentu

Podczas pobierania przez documents.get(schema, identifier):

  1. Dopasowanie UUID: jeśli identyfikator jest prawidłowym UUID, pobierz po id
  2. Pole code: sprawdź pole content.code
  3. Pole slug: sprawdź pole content.slug
  4. Dopasowanie tytułu: sprawdź pole title

Dzięki temu możesz odwoływać się do dokumentów za pomocą dowolnego unikalnego identyfikatora.

Hybryda

Projekt rendereraParametryczne RoutowanieTypy komponentówSseKonfiguracja Proxy Panelu AdministracyjnegoRenderowanie statyczne z obsługą trybu edycjiSkryptowanie W Kreatorze SzablonówCreate Profound Next

Bezgłowy

Szybki startJson I Kod ClaudeKomponent Zod Pobieranie

Mcp

Mcp

Funkcje Cms

Funkcja Szablon DokumentacjiFunkcja Kreator SzablonówFeat TłumaczFunkcja Organizacja

Motywacja

Nasze podejście

Terminologia

Hybrydowe Vs Headless
]
] }
:
"ようこそ"
,
"subheadline"
:
"私たちのプラットフォームへようこそ"
}
,
"type"
:
"string"
},
{ "name": "ctaText", "type": "string" },
{ "name": "ctaUrl", "type": "string" }
]
}
const
client
=
getCmsClient
({
cmsUrl: process.env.CMS_URL!,
apiKey: process.env.CMS_API_KEY!,
websiteId: process.env.CMS_WEBSITE_ID!,
});
const path = '/' + params.slug.join('/');
// Pobierz trasę i rozstrzygnięte parametry
const { route, resolvedParams } = await client.routes.getRouteByPath.query({
websiteId: process.env.CMS_WEBSITE_ID!,
path,
});
// Pobierz bloki dla trasy
const blocks = await client.blocks.getBlocks.query({
websiteId: process.env.CMS_WEBSITE_ID!,
blockIds: route.block_ids,
// Przekaż rozstrzygnięte parametry dla kontekstu CEL
context: {
meta: {
locale: resolvedParams?.lang?.document?.content?.code ?? 'en',
params: Object.fromEntries(
Object.entries(resolvedParams ?? {}).map(([k, v]) => [k, v.value])
),
segments: params.slug,
docId: null,
title: route.title ?? '',
},
schema: {},
},
});
// Renderuj bloki
return (
<main>
{blocks.map((block) => (
<BlockRenderer
key={block.id}
block={block}
routeParams={resolvedParams}
language={resolvedParams?.lang?.value}
/>
))}
</main>
);
}
docId: string | null;
/** Tytuł bieżącego dokumentu */
title: string;
}
3. Dopasować liczbę segmentów (musi być taka sama)
4. Dla każdej pary segmentów:
- Jeśli wzorzec zaczyna się od : lub {}, wyodrębnić jako parametr
- W innym przypadku segmenty muszą być identyczne
5. Zwrócić: { country: "us", lang: "en" }
}