// 경량 i18n — ?lang=en 쿼리로 한/영 전환. SSG 유지(서버에서 lang 주입). import type { Team } from "./types"; export type Lang = "ko" | "en"; export function parseLang(v: unknown): Lang { return v === "en" ? "en" : "ko"; } // 팀 짧은 표기 (KO=한글, EN=영문 약식) const TEAM_EN: Record = { KOR: "Korea", CZE: "Czechia", MEX: "Mexico", RSA: "S. Africa", }; export function teamShort(team: Team, lang: Lang): string { return lang === "en" ? TEAM_EN[team.code] ?? team.name : team.shortName; } const DAYS: Record = { ko: ["일", "월", "화", "수", "목", "금", "토"], en: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], }; const MONTHS_EN = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; export function dayName(lang: Lang, dow: number): string { return DAYS[lang][dow]; } export function monthEn(m: number): string { return MONTHS_EN[m - 1]; } // roundLabel 안의 한국어 토막 번역 export function roundLabel(label: string, lang: Lang): string { if (lang === "ko") return label; return label.replace("개막전", "Opener"); } type Dict = { heroPill: string; back: string; share: string; shareCopied: string; introLead: string; prizeLine1: string; prizeLine2: string; schedTitle: string; schedGuide: string; phase: { open: string; scheduled: string; locked: string; live: string; finished: string }; aiPicks: string; draw: string; joined: (n: string) => string; aiBattle: string; yourPickLabel: string; yourChoice: string; win: string; drawLabel: string; winProb: (team: string) => string; drawOdds: string; ctaBeat: string; ctaResult: string; ctaLocked: string; ctaLive: string; ctaOpens: (d: string) => string; emailPh: string; notify: string; submit: string; myPick: string; sameAI: (models: string, exact: boolean) => string; soloPick: string; shareThis: string; copyLink: string; copied: string; goldDesc: string; goldBtn: string; rulesTitle: string; rulesCumulative: string; rulesExact: string; rulesCloseGrade: string; rulesOutcome: string; rulesPartial: string; rulesMiss: string; rulesEmailRequired: string; rulesCloseBtn: string; crowdSub: string; finalResult: string; exactHit: string; hit: string; miss: string; matchEnded: string; cdUntil: string; cdClosed: string; final: string; group: (g: string) => string; footerNotOfficial: string; footerDisc1: string; footerDisc2: string; footerDisc3: string; hook: (a: string, b: string) => string; moreMatches: string; commentsTitle: string; commentsCount: (n: number) => string; commentPh: string; commentAs: string; commentReroll: string; commentSubmit: string; commentMore: string; commentCollapse: string; commentEmpty: string; commentCooldown: string; commentError: string; adLabel: string; ado2Tagline: string; ado2Sub: string; ado2Cta: string; }; export const DICT: Record = { ko: { heroPill: "AI와 함께하는 2026 글로벌 축구 축전 승부예측 챌린지", back: "← 전체 일정", share: "투표 공유하기", shareCopied: "링크 복사됨 ✓", introLead: "GPT · Claude · Gemini가 매 경기를\n서로 다르게 예측합니다.", prizeLine1: "가장 많이 참여하고, 가장 정확하게 예측한", prizeLine2: "최종 우승자에게 100만원 상금", schedTitle: "전체 일정", schedGuide: "투표하고 싶은 경기를 선택해주세요", phase: { open: "투표 중", scheduled: "오픈 예정", locked: "투표 종료", live: "경기중", finished: "종료" }, aiPicks: "AI 픽", draw: "무", joined: (n) => `${n}명 참여`, aiBattle: "AI의 예측 대결", yourPickLabel: "Your Pick · 내 예측", yourChoice: "당신의 선택", win: "승", drawLabel: "무승부", winProb: (t) => `${t} 승리 확률`, drawOdds: "무승부 가능성", ctaBeat: "AI보다 잘 맞히기", ctaResult: "결과 보기", ctaLocked: "투표 종료", ctaLive: "경기 진행 중", ctaOpens: (d) => `투표 오픈 ${d}`, emailPh: "이메일 (결과·다음 경기 알림)", notify: "경기 결과가 나오면 알려주세요. 다음 경기·100만원 챌린지 소식도 받겠습니다.", submit: "제출하고 AI와 겨루기", myPick: "내 예측", sameAI: (m, exact) => `당신은 ${m}와 같은 선택입니다.${exact ? " 스코어까지 일치!" : ""} 나머지 AI는 생각이 다릅니다.`, soloPick: "당신은 AI 셋 모두와 다른 선택! 소신 픽 🔥", shareThis: "이 경기 공유하기", copyLink: "링크 복사", copied: "복사됨 ✓", goldDesc: "경기마다 승패·스코어를 맞혀 포인트를 쌓고, 누적 1위에게 최종 100만원", goldBtn: "100만 원에\n도전하기", rulesTitle: "100만 원 챌린지 룰", rulesCumulative: "경기마다 적중 포인트를 쌓아, 대회 누적 포인트 1위 한 분에게 최종 100만 원을 드립니다.", rulesExact: "정확 스코어 적중", rulesCloseGrade: "근접 (승패 + 득실차 일치)", rulesOutcome: "승패만 적중", rulesPartial: "부분 (한 팀 스코어만 일치)", rulesMiss: "빗나감", rulesEmailRequired: "픽 제출 시 입력한 이메일로 챌린지에 참여됩니다. 같은 이메일의 모든 경기 포인트가 합산되어 누적 순위가 매겨집니다.", rulesCloseBtn: "확인", crowdSub: "| 참여자들의 선택", finalResult: "최종 결과", exactHit: "정확 ✓", hit: "적중 ✓", miss: "빗나감", matchEnded: "경기 종료 · 최종 결과", cdUntil: "투표 종료까지", cdClosed: "투표가 마감되었습니다", final: "Final", group: (g) => `Group ${g}`, footerNotOfficial: "Independent AI prediction game — not affiliated with, endorsed by, or sponsored by FIFA or the official World Cup.", footerDisc1: "FIFA 및 공식 월드컵과 무관한 독립 AI 예측 게임입니다 (제휴·후원·운영 아님).", footerDisc2: "스포츠 분석·엔터테인먼트 목적의 예측 게임이며 베팅·도박을 권유하지 않습니다. AI 예측은 실제 결과를 보장하지 않습니다.", footerDisc3: "100만 원 이벤트는 무료 참여형 챌린지입니다. 지급·동점 처리 조건은 별도 약관에 따릅니다. 이메일은 결과·이벤트 알림 목적으로만 사용됩니다.", hook: (a, b) => `${a} vs ${b}, AI의 선택은 갈렸다`, moreMatches: "다른 경기 투표하기", commentsTitle: "한마디", commentsCount: (n) => `총 ${n}개`, commentPh: "응원 한마디 남기기...", commentAs: "이번 닉네임", commentReroll: "닉네임 새로 뽑기", commentSubmit: "등록", commentMore: "댓글 더보기", commentCollapse: "접기", commentEmpty: "첫 한마디를 남겨보세요!", commentCooldown: "잠시 후 다시 시도해주세요.", commentError: "등록에 실패했습니다. 잠시 후 다시 시도해주세요.", adLabel: "광고", ado2Tagline: "AI 마케팅 자동화 플랫폼", ado2Sub: "AI Marketing Automation Platform →", ado2Cta: "사용해보기", }, en: { heroPill: "AI-powered Global Football Festival 2026 match predictions", back: "← All matches", share: "Share vote", shareCopied: "Link copied ✓", introLead: "GPT · Claude · Gemini predict\nevery match differently.", prizeLine1: "The most active, most accurate", prizeLine2: "overall winner takes ₩1,000,000", schedTitle: "All Matches", schedGuide: "Pick a match to predict", phase: { open: "Voting", scheduled: "Opens soon", locked: "Closed", live: "Live", finished: "Ended" }, aiPicks: "AI picks", draw: "Draw", joined: (n) => `${n} joined`, aiBattle: "AI Prediction Battle", yourPickLabel: "Your Pick", yourChoice: "Your Choice", win: "Win", drawLabel: "Draw", winProb: (t) => `${t} win prob.`, drawOdds: "Draw odds", ctaBeat: "Beat the AI", ctaResult: "View result", ctaLocked: "Voting closed", ctaLive: "Match in progress", ctaOpens: (d) => `Opens ${d}`, emailPh: "Email (result & next-match alerts)", notify: "Notify me when the result is out. I'll also get next-match & ₩1,000,000 challenge news.", submit: "Submit & face the AI", myPick: "My Pick", sameAI: (m, exact) => `You matched ${m}.${exact ? " Exact score too!" : ""} The other AIs disagree.`, soloPick: "You disagree with all three AIs — bold pick 🔥", shareThis: "Share this match", copyLink: "Copy link", copied: "Copied ✓", goldDesc: "Earn points each match by nailing the result & score — the overall #1 wins ₩1,000,000.", goldBtn: "Go for\n₩1,000,000", rulesTitle: "₩1,000,000 Challenge Rules", rulesCumulative: "Earn points each match — the player with the highest cumulative total wins ₩1,000,000.", rulesExact: "Exact score", rulesCloseGrade: "Close (result + goal difference)", rulesOutcome: "Correct result only", rulesPartial: "Partial (one team's score)", rulesMiss: "Miss", rulesEmailRequired: "You enter the challenge with the email you provide when submitting a pick. Points from all matches under the same email are summed for the overall ranking.", rulesCloseBtn: "Got it", crowdSub: "| What the crowd picked", finalResult: "Final result", exactHit: "Exact ✓", hit: "Hit ✓", miss: "Miss", matchEnded: "Match ended · Final", cdUntil: "Voting closes in", cdClosed: "Voting closed", final: "Final", group: (g) => `Group ${g}`, footerNotOfficial: "Independent AI prediction game — not affiliated with, endorsed by, or sponsored by FIFA or the official World Cup.", footerDisc1: "A fan-run prediction game using public match schedules; all picks are independent.", footerDisc2: "A sports-analysis & entertainment prediction game. No betting or gambling. AI predictions do not guarantee real outcomes.", footerDisc3: "The ₩1,000,000 event is a free-to-enter challenge. Payout & tie-break terms follow separate rules. Email is used only for result & event alerts.", hook: (a, b) => `AI is split on ${a} vs ${b}`, moreMatches: "Vote on another match", commentsTitle: "Comments", commentsCount: (n) => `${n} total`, commentPh: "Leave a comment...", commentAs: "Your name", commentReroll: "Get a new name", commentSubmit: "Post", commentMore: "Show more", commentCollapse: "Collapse", commentEmpty: "Be the first to comment!", commentCooldown: "Please wait a moment before posting again.", commentError: "Failed to post. Please try again shortly.", adLabel: "AD", ado2Tagline: "AI Marketing Automation Platform", ado2Sub: "Visit ado2.o2osolution.ai →", ado2Cta: "Try it", }, }; export function dict(lang: Lang): Dict { return DICT[lang]; }