Files
tibi-docs/src/content/docs/projekt/navigation-i18n.md
T
apairon 1897bb50d9
Deploy tibi-docs / build-and-deploy (push) Failing after 38s
Doku-Vollausbau: 62 Seiten (Projekt/Admin/Anwender/Referenz), Hook-Referenz mit Signaturen, Corporate-Screenshots, Coverage-Inventar
- 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
2026-10-16 22:49:07 +00:00

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
  1. Lege je Sprache einen Header und einen Footer an, je mit active:true (Pflicht trotz fehlendem Schema-Feld — siehe Kasten unten).

  2. Löse Seiten mit Lookup auf:

    GET …/navigation?lookup=elements.page:content
    
  3. Baue den Link aus dem Lookup: href = lokalisierter _lookup.page.path plus hash. 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-uns statt /Über-uns).
  • Unique-Index path + lang: gleicher Pfad in de und en ist okay, zweimal in de nicht.
  • 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)