init localize

This commit is contained in:
2026-07-01 10:56:47 -05:00
parent 275dda65e0
commit dca3a66206
18 changed files with 1008 additions and 25 deletions

145
lib/i18n/en.ts Normal file
View File

@@ -0,0 +1,145 @@
import { Dictionary } from "./types";
function ordinal(n: number): string {
const s = ["th", "st", "nd", "rd"];
const v = n % 100;
return n + (s[(v - 20) % 10] || s[v] || s[0]);
}
const en: Dictionary = {
meta: {
title: "WC 26 — Groups & KO Bracket",
description:
"Live group tables, third-place ranking and the complete KO bracket for the FIFA World Cup 2026 with Annex C assignment and Polymarket probabilities.",
},
header: {
hostCountries: "USA · Canada · Mexico",
},
status: {
feedOffline: "Feed offline",
updated: (time: string) => `Updated ${time}`,
live: "Live",
loading: "Loading…",
running: "running",
halftime: "Half time",
finished: "Finished",
postponed: "Postponed",
},
nav: {
koFixtures: "KO Matches",
groups: "Groups",
groupFixtures: (group: string) => `Group Stage ${group}`,
groupFixturesNoGroup: "Group Stage",
thirdPlace: "Third Place",
bracket: "KO Bracket",
simulation: "Simulation",
},
error: {
feedUnreachable:
"Live feeds are currently unavailable. The page will retry automatically.",
unknown: "unknown error",
},
footer: {
dashboard: "WC 2026 Dashboard",
dataSources: "Data: football-data.org · Polymarket Gamma API · FIFA Annex C",
},
sim: {
notice:
"Simulation — all unplayed matches are pre-filled with the Polymarket favourite. Probabilities shown are from Polymarket.",
heading: "Simulated KO Bracket",
},
koFixtures: {
noMatches: "No KO matches with known teams available.",
liveBadge: "LIVE",
nextMatch: "NEXT MATCH",
postponedBadge: "POSTPONED",
match: (n: number) => `Match ${n}`,
},
label: {
goals: "Goals",
liveIndicator: "● LIVE",
scrollToTop: "Scroll to top",
securelyQualified: "securely qualified",
},
stage: {
r16: "Round of 16",
qf: "Quarter-finals",
sf: "Semi-finals",
thirdPlace: "3rd Place",
final: "Final",
},
round: {
r32: "Round of 32",
r16: "Round of 16",
qf: "Quarter-finals",
sf: "Semi-finals",
final: "Final",
thirdPlace: "Third Place Match",
},
bracket: {
provisionalTooltip: "provisional group/assignment not yet fixed",
match: (n: number) => `Match ${n}`,
penaltyShootout: "PSO",
annexHeader: "Annex C third-place assignment:",
annexResolved:
"resolved — the eight third-placed teams are permanently assigned to group winners",
annexPending:
"pending — once the 8 best third-placed teams are determined, the bracket auto-connects",
winner: "Winner",
loser: "Loser",
winnerFromMatch: (n: number) => `Winner of match ${n}`,
loserFromMatch: (n: number) => `Loser of match ${n}`,
},
legend: {
winner: "Winner / advances",
final: "Final",
fixed: "securely qualified",
provisional: "provisional (≈, current standings)",
placeholder: "placeholder open",
probExplanation: "% values: Polymarket probability (if available)",
},
tooltips: {
provisionalPrefix: "currently",
firstOfGroup: (group: string) => `${ordinal(1)} in Group ${group}`,
secondOfGroup: (group: string) => `${ordinal(2)} in Group ${group}`,
thirdOfGroup: (group: string) => `${ordinal(3)} in Group ${group}`,
provisionalThird: (pool: string) => `currently 3rd of Group ${pool}`,
},
slot: {
winner: (group: string) => `Winner ${group}`,
runnerUp: (group: string) => `Runner-up ${group}`,
thirdOfGroup: (group: string) => `3rd of Group ${group}`,
thirdPlacePool: (pool: string) => `3rd ${pool}`,
},
table: {
rank: "#",
team: "Team",
group: "Group",
matches: "GP",
won: "W",
drawn: "D",
lost: "L",
goals: "Goals",
goalDiff: "±",
points: "Pts",
status: "Status",
},
thirds: {
explanation:
"Eight of the twelve group third-placed teams advance to the Round of 32. Ranking is across all groups by points, goal difference and goals scored — head-to-head does not apply because these teams have never met. The separator marks the cut between 8th and 9th place.",
advances: "advances",
eliminated: "out",
},
fixtures: {
standingsTitle: (group: string) => `Standings Group ${group}`,
noMatches: (group: string) =>
`No matches available yet for Group ${group}.`,
},
groups: {
viewGroupGames: (group: string) => `View Group ${group} matches`,
groupLabel: (group: string) => `Group ${group}`,
viewGames: "View matches →",
},
};
export default en;