- Einstieg: Schnellstart + Neues Projekt aus Starter-Skill, Was-ist-Tibi mit Backend/Website-Trennung - Projekt: Sammlungen, Felder, Abfragen, Rechte, Hooks, Dateien, i18n, Suche, SSR, Pagebuilder, Jobs, Audit, Deploy, LLM, MCP - Hook-Referenz: 66 Symbole mit Signatur + Beispiel + Fehlerfall (5 Kapitel) - Admin: Ansichten, Editor, Medien, Exporte, Aktionen, Rechte, KI, Setup, Customizing - Anwender: 11 Anleitungen im professionellen Du-Ton, 30 Corporate-Screenshots - Referenz: Schemas, Token-Köpfe, Fehlerbilder, Shortcuts, OpenAPI-Platzhalter - ADR-0001 bis 0003, Coverage-Skript (282 Items) + Map, Plan-Dateien
5.2 KiB
title, description
| title | description |
|---|---|
| Navigation und Sprachen | Navigations-Collection, Sprachfelder, translationKey, Pfad-Regeln. |
import { Aside, Tabs, TabItem, Steps } from '@astrojs/starlight/components';
Navigation und Sprachen hängen zusammen: Die navigation-Sammlung hält je Sprache einen Baum, content hält je Sprache einen Eintrag.
Suche-Begriffe: Navigation anlegen, Sprache umschalten, translationKey.
Navigations-Dokumente
api/collections/navigation.yml kennt genau vier Singleton-Bäume: type (header, footer) mal language (de, en) — abgesichert per Unique-Index type_language.
# navigation.yml — Felder (gekürzt)
fields:
- name: language # de | en, Pflicht
- name: type # header | footer, Pflicht
- name: elements # object[]: {name, page?, external?, externalUrl?, hash?, elements?}
| Element-Art | Felder | Beispiel |
|---|---|---|
| Intern | name + page (= content-ID) |
{name: "Start", page: "<content.id>"} |
| Extern | name + external: true + externalUrl |
{name: "Blog", external: true, externalUrl: "https://…"} |
| Anker | zusätzlich hash ohne #, Muster ^[a-zA-Z0-9_-]+$ |
{name: "Kontakt", page: "<id>", hash: "kontakt"} |
| Unterpunkt | geschachtelt in elements.elements |
Header max. 2 Ebenen, Footer max. 1 |
-
Lege je Sprache einen Header und einen Footer an, je mit
active:true(Pflicht trotz fehlendem Schema-Feld — siehe Kasten unten). -
Löse Seiten mit Lookup auf:
GET …/navigation?lookup=elements.page:content -
Baue den Link aus dem Lookup:
href= lokalisierter_lookup.page.pathplushash. Den/de-Präfix nie in die DB schreiben.
Sprachmodell: lang + translationKey
content.yml nutzt Entry-i18n: eine Sprache je Eintrag, verbunden über den Schlüssel.
# content.yml — i18n-Block (gekürzt)
meta:
i18n:
entry:
languageField: lang
groupField: translationKey
| Regel | Konkret |
|---|---|
lang |
Sprachkürzel, z. B. de, en |
translationKey |
Pflicht, z. B. home, ueber-uns — pro Sprache eindeutig (Unique-Index translationKey + lang) |
| Zweiter Datensatz ohne Schlüssel | Kollidiert auf null — kein „geht schon gut" |
path |
Ohne Sprachpräfix gespeichert (/ueber-uns), URL mit Präfix (/de/ueber-uns) |
alternativePaths[].path |
Alte Pfade, gleiches Muster wie path |
Die Feld-i18n (Tabs je Feld, Test-Plan 34-i18n-fields) und Entry-i18n (eine Sprache je Eintrag, Test-Plan 35-entry-i18n) pflegst du im tibi-admin; das Datenmodell aus Projekt-Sicht ist immer lang + translationKey.
Pfad-Regeln
^/[a-z0-9-/]*$ → gilt für path und alternativePaths[].path
- Nur Kleinbuchstaben, Ziffern,
-und/; keine Großbuchstaben, keine Umlaute (/ueber-unsstatt/Über-uns). - Unique-Index
path+lang: gleicher Pfad indeundenist okay, zweimal indenicht. - SSR streift den Präfix vor der Suche ab und liefert die kanonische URL zurück (
hooks/config.js→ssrValidatePath).
active:true auch hier (Checkliste)
| Sammlung | Ohne active:true öffentlich … |
|---|---|
content |
… filtern filter_public + SSR-Prüfung den Eintrag weg |
medialib |
… bleibt _lookup leer, Bilder verschwinden (siehe Dateien und Bilder) |
navigation |
… ist Header/Footer leer |
Prüfung: anonyme SSR-Nav-Zahl
GET …/navigation?filter={"language":"de"}
GET …/navigation?filter={"language":"en"}
# anonym (ohne Token) müssen beide je einen Header und einen Footer liefern
GET …/ssr?url=/de/
# im HTML: window.__SSR_CACHE__ enthält das Ergebnis je Request (cacheKey mit data + count) — Navigation darin je Sprache mit count > 0 prüfen; die Abhängigkeiten selbst stehen separat im ssr-Dokument (Feld dependencies)
| Fehlerbild | Ursache | Lösung |
|---|---|---|
| Öffentliche Nav leer, mit Token voll | active:true fehlt |
Auf allen vier Bäumen setzen |
409 beim zweiten Spracheintrag |
translationKey fehlt oder doppelt |
Eindeutigen Schlüssel je Sprache vergeben |
400 beim Speichern |
Pfad mit Großbuchstaben/Umlaut | Kleinschreiben, Muster einhalten |
| Falsche Sprache im SSR | lang-Feld passt nicht zum Präfix |
lang und URL-Präfix angleichen |
Weiter: Lesen und suchen, Dateien und Bilder, Rechte und Tokens.
Verifiziert am e3f92ebf 2026-10-14 (tibi-svelte-starter), am 2b091d89 2026-10-13 (tibi-admin-nova, Test-Pläne 34-i18n-fields, 35-entry-i18n)