localized team names

This commit is contained in:
2026-06-24 12:17:46 -05:00
parent aa19c16f93
commit 7996ebc504
9 changed files with 79 additions and 10 deletions

View File

@@ -101,7 +101,7 @@ function GroupStandings({
<td className="team">
<span className={`rankdot ${cls}`}>{r.rank}</span>
<Flag team={team} size={20} />
<span className="team-name">{team?.name ?? r.teamId}</span>
<span className="team-name">{team?.localisedName ?? team?.name ?? r.teamId}</span>
{isLive && <span className="row-live-dot" title="läuft gerade" />}
</td>
<td>{r.played}</td>
@@ -163,12 +163,12 @@ export default function Fixtures({
<div className="fx-teams">
<div className={`fx-team home ${homeWin ? "win" : ""}`}>
<Flag team={home} size={22} />
<span className="fx-name">{home?.name ?? "—"}</span>
<span className="fx-name">{home?.localisedName ?? home?.name ?? "—"}</span>
</div>
<ScoreCell m={m} />
<div className={`fx-team away ${awayWin ? "win" : ""}`}>
<Flag team={away} size={22} />
<span className="fx-name">{away?.name ?? "—"}</span>
<span className="fx-name">{away?.localisedName ?? away?.name ?? "—"}</span>
</div>
</div>
<div className="fx-meta">

View File

@@ -13,7 +13,7 @@ export default function Flag({
return (
<img
src={team.crest}
alt={team.code || team.name}
alt={team.code || team.localisedName || team.name}
className="flag"
style={style}
loading="lazy"

View File

@@ -66,7 +66,7 @@ export default function Groups({
<td className="team">
<span className={`rankdot ${cls}`}>{r.rank}</span>
<Flag team={team} size={20} />
<span className="team-name">{team?.name ?? r.teamId}</span>
<span className="team-name">{team?.localisedName ?? team?.name ?? r.teamId}</span>
{isLive && <span className="row-live-dot" title="läuft gerade" />}
</td>
<td>{r.played}</td>

View File

@@ -298,7 +298,7 @@ function SimRow({
<span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1, justifyContent: "flex-end" }}>
<Flag team={home} size={18} />
<span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
{home?.name ?? "—"}
{home?.localisedName ?? home?.name ?? "—"}
</span>
</span>
<input
@@ -338,7 +338,7 @@ function SimRow({
/>
<span style={{ display: "flex", alignItems: "center", gap: 6, minWidth: 0, flex: 1 }}>
<span style={{ fontWeight: 600, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 140 }}>
{away?.name ?? "—"}
{away?.localisedName ?? away?.name ?? "—"}
</span>
<Flag team={away} size={18} />
</span>

View File

@@ -5,7 +5,10 @@ import { Team, ThirdPlaceRow } from "@/lib/types";
export default function ThirdPlace({
rows, teams,
}: { rows: ThirdPlaceRow[]; teams: Team[] }) {
const name = (id: string) => teams.find((t) => t.id === id)?.name ?? id;
const name = (id: string) => {
const t = teams.find((t) => t.id === id);
return t?.localisedName ?? t?.name ?? id;
};
return (
<div className="third-wrap">

View File

@@ -1,5 +1,6 @@
import { GroupId, Match, MatchStatus, Team } from "./types";
import { venueFor } from "./venues";
import { localisedTeamName } from "./team-mappings";
// ----------------------------------------------------------------------------
// Caching: einfacher In-Memory-Cache mit TTL. Verhindert, dass jede Browser-
@@ -129,6 +130,7 @@ export async function fetchMatchesAndTeams(): Promise<{ matches: Match[]; teams:
teamMap.set(id, {
id, name: side.name, code: side.tla ?? "", group,
crest: side.crest ?? null,
localisedName: localisedTeamName(side.tla ?? "", side.name ?? ""),
});
}
}

View File

@@ -120,7 +120,7 @@ function sideFrom(
const w = winnerOf(feed);
return {
teamId,
label: team?.name ?? fallbackLabel,
label: team?.localisedName ?? team?.name ?? fallbackLabel,
code: team?.code ?? "",
score,
isWinner: teamId != null && w === teamId,

63
lib/team-mappings.ts Normal file
View File

@@ -0,0 +1,63 @@
// Zentrale Lokalisierungstabelle für Teamnamen (TLA → Deutsch / Englisch).
// Schlüssel = FIFA-3-Buchstaben-Code (uppercase), wie er von football-data.org
// im Feld `tla` geliefert wird.
//
// Erweiterung auf weitere Sprachen: einfach pro Sprache ein Feld ergänzen.
export const TEAM_LOCALIZATION: Record<string, { de: string; en: string }> = {
ALG: { de: "Algerien", en: "Algeria" },
ARG: { de: "Argentinien", en: "Argentina" },
AUS: { de: "Australien", en: "Australia" },
AUT: { de: "Österreich", en: "Austria" },
BEL: { de: "Belgien", en: "Belgium" },
BIH: { de: "Bosnien-Herzegowina", en: "Bosnia-Herzegovina" },
BRA: { de: "Brasilien", en: "Brazil" },
CAN: { de: "Kanada", en: "Canada" },
CHE: { de: "Schweiz", en: "Switzerland" },
CIV: { de: "Elfenbeinküste", en: "Ivory Coast" },
COD: { de: "DR Kongo", en: "Congo DR" },
COL: { de: "Kolumbien", en: "Colombia" },
CPV: { de: "Kap Verde", en: "Cape Verde" },
CZE: { de: "Tschechien", en: "Czech Republic" },
ECU: { de: "Ecuador", en: "Ecuador" },
EGY: { de: "Ägypten", en: "Egypt" },
ENG: { de: "England", en: "England" },
ESP: { de: "Spanien", en: "Spain" },
FRA: { de: "Frankreich", en: "France" },
GER: { de: "Deutschland", en: "Germany" },
GHA: { de: "Ghana", en: "Ghana" },
HAI: { de: "Haiti", en: "Haiti" },
HRV: { de: "Kroatien", en: "Croatia" },
IRN: { de: "Iran", en: "Iran" },
IRQ: { de: "Irak", en: "Iraq" },
JOR: { de: "Jordanien", en: "Jordan" },
JPN: { de: "Japan", en: "Japan" },
KOR: { de: "Südkorea", en: "South Korea" },
KSA: { de: "Saudi-Arabien", en: "Saudi Arabia" },
MAR: { de: "Marokko", en: "Morocco" },
MEX: { de: "Mexiko", en: "Mexico" },
NED: { de: "Niederlande", en: "Netherlands" },
NOR: { de: "Norwegen", en: "Norway" },
NZL: { de: "Neuseeland", en: "New Zealand" },
PAN: { de: "Panama", en: "Panama" },
PAR: { de: "Paraguay", en: "Paraguay" },
PRT: { de: "Portugal", en: "Portugal" },
QAT: { de: "Katar", en: "Qatar" },
RSA: { de: "Südafrika", en: "South Africa" },
SCO: { de: "Schottland", en: "Scotland" },
SEN: { de: "Senegal", en: "Senegal" },
SWE: { de: "Schweden", en: "Sweden" },
TUN: { de: "Tunesien", en: "Tunisia" },
TUR: { de: "Türkei", en: "Turkey" },
URU: { de: "Uruguay", en: "Uruguay" },
USA: { de: "USA", en: "USA" },
UZB: { de: "Usbekistan", en: "Uzbekistan" },
};
// Liefert den lokalisierten Namen für ein Team in der gewünschten Sprache.
// Fallback: originalName (englischer Feed-Name), wenn kein Eintrag existiert.
export function localisedTeamName(tla: string, originalName: string, lang: "de" | "en" = "de"): string {
const entry = TEAM_LOCALIZATION[tla.toUpperCase()];
if (entry) return entry[lang];
return originalName;
}

View File

@@ -11,10 +11,11 @@ export const GROUP_IDS: GroupId[] = [
export interface Team {
id: string; // stabile ID aus dem Feed
name: string; // Anzeigename
name: string; // Originalname aus dem Feed (englisch)
code: string; // 3-Buchstaben-Code, z.B. GER
group: GroupId;
crest?: string | null; // URL zur Flagge / zum Wappen (football-data: crest)
localisedName: string; // Lokalisierter Anzeigename (z.B. "Deutschland")
}
export type MatchStatus =