Team-Personendaten (role/bio/bioHtml/intro/quote) jetzt mehrsprachig

Bisher waren role/bio/bioHtml/intro/quote in data-scouts.js und
data-modis.js reine deutsche Strings — dadurch blieben z.B. Zitate
("Ein Mann, ein Wort.") und Kurzrollen auch bei gewählter Fremdsprache
Deutsch (siehe Screenshot-Hinweis: team-scouts.html in EN zeigte noch
deutsches Zitat).

- main.js: neuer window.dogiFeld()-Helper löst mehrsprachige Feld-Objekte
  { de, "de-CH", en, fr, pt } auf (rückwärtskompatibel zu reinen Strings).
- data-scouts.js: role (Patrick, Bananenstift) + bio (Patrick) + intro/
  bioHtml/quote (Bananenstift) vollständig in allen 5 Sprachen.
- data-modis.js: role (alle 7) + bio (VanVan/Funny/Marina/Michi) +
  bioHtml (Diene/Miss/Ghost) + rankLabel (Ghost) vollständig in allen
  5 Sprachen. Lange bioHtml-Texte von unabhängigen Übersetzer-Agenten
  erstellt, idiomatisch statt wörtlich.
- team-scouts.html, team-modis.html, index.html (Team-Vorschau),
  profil.html: Rendering nutzt jetzt durchgängig dogiFeld() und rendert
  bei Sprachwechsel (dogi-sprache-geaendert) neu — team-modis.html und
  die Team-Vorschau auf index.html haben vorher GAR NICHT auf Sprach-
  wechsel reagiert, das ist jetzt behoben. "Stufe"/"Profil ansehen" auf
  team-modis.html liefen bisher hart kodiert Deutsch, jetzt über
  i18n-team-modis.js.
This commit is contained in:
2026-08-02 11:29:47 +02:00
parent 95969c001c
commit 2eb9fc6897
8 changed files with 541 additions and 81 deletions
+36 -31
View File
@@ -157,18 +157,16 @@ document.addEventListener("DOMContentLoaded", () => {
document.body.style.setProperty("--page-bg-mobile", `url('/assets/img/${bgBasis}-mobile.jpg')`);
document.title = `${person.name} — DOGFATHER UNIVERSE`;
// Personendaten-Felder (role/bio/bioHtml/intro/quote/rankLabel) sind
// entweder weiterhin reine Strings (z.B. leere Zitate) oder mehrsprachige
// Objekte { de, "de-CH", en, fr, pt } — siehe window.dogiFeld() in main.js.
const feld = (x) => (window.dogiFeld ? window.dogiFeld(x) : x || "");
// Für die Meta-Beschreibung reicht immer ein kurzer Textauszug, auch
// wenn die eigentliche Vorstellung als bioHtml (langer, formatierter
// Text) vorliegt statt als einfacher bio-String.
const kurzbeschreibung = person.bio
|| (person.bioHtml ? person.bioHtml.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 160) : "")
|| person.role
|| person.name;
const metaDesc = document.querySelector('meta[name="description"]');
if (metaDesc) metaDesc.setAttribute("content", kurzbeschreibung);
document.getElementById("profil-hero-name").textContent = person.name;
document.getElementById("profil-hero-role").textContent = person.role || "";
// Rahmenfarbe abwechslungsreich, aber für dieselbe Person immer gleich
const farben = ["frame-lila", "frame-silver", "frame-gold", "frame-tuerkis", ""];
@@ -189,26 +187,15 @@ document.addEventListener("DOMContentLoaded", () => {
);
document.getElementById("profil-name").textContent = person.name;
document.getElementById("profil-role").textContent = person.role || "";
// Zwei Modi: entweder eine ausführliche, formatierte Vorstellung
// (bioHtml — beliebig lang, mit Absätzen und Zwischenüberschriften),
// oder der kurze einzeilige Standardtext (bio). bioHtml hat Vorrang.
// Optional: person.intro — ein kurzer Einstiegstext (1-2 Absätze), der
// direkt neben dem großen Foto angezeigt wird, auch wenn bioHtml gesetzt
// ist (die ausführliche Vorstellung erscheint zusätzlich weiter unten).
// Struktur-Sichtbarkeit hängt nur davon ab, OB ein Feld existiert (nicht
// von der Sprache) — daher einmalig hier, unabhängig von der reaktiven
// Textbefüllung in renderStatischeTexte() weiter unten.
if (person.bioHtml) {
if (person.intro) {
document.getElementById("profil-bio").innerHTML = person.intro;
document.getElementById("profil-bio").style.display = "";
} else {
document.getElementById("profil-bio").style.display = "none";
}
const richSection = document.getElementById("profil-bio-rich-section");
document.getElementById("profil-bio-rich").innerHTML = person.bioHtml;
richSection.style.display = "";
if (person.intro) document.getElementById("profil-bio").style.display = "";
else document.getElementById("profil-bio").style.display = "none";
document.getElementById("profil-bio-rich-section").style.display = "";
}
if (person.rank) {
document.getElementById("profil-badge").style.display = "inline-block";
}
@@ -219,7 +206,9 @@ document.addEventListener("DOMContentLoaded", () => {
// Rahmentexte, die je nach Sprache und Team-Zugehörigkeit (Modi/Scout/
// Creator) unterschiedlich ausfallen — per JS statt data-i18n gesetzt,
// damit sie bei jedem Sprachwechsel (dogi-sprache-geaendert) sauber
// neu übersetzt werden, ohne die eigentlichen Personendaten anzufassen.
// neu übersetzt werden. Auch die eigentlichen Personendaten (role/bio/
// bioHtml/intro/quote/rankLabel) werden hier über feld() aufgelöst, damit
// sie bei einem Sprachwechsel ebenfalls sofort aktualisiert werden.
const renderStatischeTexte = () => {
document.getElementById("profil-eyebrow").textContent = istScout
? t("pr_eyebrow_scout")
@@ -227,16 +216,32 @@ document.addEventListener("DOMContentLoaded", () => {
? t("pr_eyebrow_creator")
: t("pr_eyebrow_default");
if (!person.bioHtml) {
document.getElementById("profil-hero-name").textContent = person.name;
document.getElementById("profil-hero-role").textContent = feld(person.role);
document.getElementById("profil-role").textContent = feld(person.role);
const introText = feld(person.intro);
const bioHtmlText = feld(person.bioHtml);
if (bioHtmlText) {
if (introText) document.getElementById("profil-bio").innerHTML = introText;
document.getElementById("profil-bio-rich").innerHTML = bioHtmlText;
} else {
document.getElementById("profil-bio").textContent =
person.bio || t("pr_bio_fallback").replace("{name}", person.name);
feld(person.bio) || t("pr_bio_fallback").replace("{name}", person.name);
}
const kurzbeschreibung = feld(person.bio)
|| (bioHtmlText ? bioHtmlText.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim().slice(0, 160) : "")
|| feld(person.role)
|| person.name;
if (metaDesc) metaDesc.setAttribute("content", kurzbeschreibung);
if (person.rank) {
document.getElementById("profil-badge").textContent = `${t("pr_badge_prefix")} ${person.rankLabel || person.rank}`;
document.getElementById("profil-badge").textContent = `${t("pr_badge_prefix")} ${feld(person.rankLabel) || person.rank}`;
}
if (person.quote) {
document.getElementById("profil-quote").textContent = `${t("pr_quote_open")}${person.quote}${t("pr_quote_close")}`;
const quoteText = feld(person.quote);
if (quoteText) {
document.getElementById("profil-quote").textContent = `${t("pr_quote_open")}${quoteText}${t("pr_quote_close")}`;
}
const zurueck = document.getElementById("profil-back");