// Static message catalogs for the admin dashboard. Default locale is English.
export const LOCALES = ["en", "ko"] as const;
export type Locale = (typeof LOCALES)[number];
export const defaultLocale: Locale = "en";

export const localeNames: Record<Locale, string> = {
  en: "English",
  ko: "한국어",
};

const en = {
  common: { appName: "Admin" },
  landing: { title: "Welcome", subtitle: "This is your app's home page. Replace it with your own content — the admin area lives under /admin.", openAdmin: "Open admin" },
  footer: { support: "Support", terms: "Terms", privacy: "Privacy" },
  maintenance: { title: "Under maintenance", subtitle: "The site is temporarily unavailable. Please check back soon.", adminHint: "Administrators can sign in to manage the site.", signIn: "Admin sign in" },
  language: { label: "Language" },
  toolbar: { filter: "Filter", search: "Search", searchButton: "Search", all: "All" },
  theme: { toggle: "Toggle theme", light: "Light", dark: "Dark", system: "System" },
  auth: {
    signInTitle: "Sign in",
    signInDesc: "Enter your credentials to continue.",
    email: "Email",
    emailOrUsername: "Email or username",
    password: "Password",
    forgot: "Forgot?",
    signIn: "Sign in",
    signingIn: "Signing in…",
    magicLinkButton: "Email me a sign-in link",
    passkeyButton: "Use a passkey",
    magicLinkSent: "Check your email for a sign-in link.",
    magicLinkNeedsEmail: "Enter your email first.",
    otpButton: "Email me a code", otpCode: "One-time code", otpVerify: "Verify code",
    noAccount: "No account?",
    signUp: "Sign up",
    signInFailed: "Sign in failed",
    createTitle: "Create account",
    createDesc: "Sign up to get started.",
    name: "Name",
    create: "Create account",
    creating: "Creating…",
    haveAccount: "Have an account?",
    signUpFailed: "Sign up failed",
    resetTitle: "Reset password",
    resetDesc: "We'll send a reset link to your email.",
    sendReset: "Send reset link",
    sending: "Sending…",
    resetSent: "If that email exists, a reset link is on its way.",
    backToSignIn: "Back to sign in",
    requestFailed: "Request failed",
    newTitle: "Set a new password",
    newPassword: "New password",
    updatePassword: "Update password",
    updating: "Updating…",
    missingToken: "Missing or invalid reset token.",
    resetFailed: "Reset failed",
    verifyTitle: "Verify your email",
    verifyDesc: "We sent a verification link to {email}. Open it to activate your account.",
    verifyDescNoEmail: "Enter your email to receive a new verification link.",
    verifySent: "Verification email sent — check your inbox.",
    verifyLinkError: "That verification link is invalid or has expired. Request a new one below.",
    resendVerification: "Resend verification email",
    emailNotVerified: "Verify your email before signing in.",
  },
  nav: { overview: "Overview", users: "Users", sessions: "Sessions", organizations: "Organizations", audit: "Audit log", account: "Account", settings: "Settings", home: "Back to home", signOut: "Sign out" },
  passkeys: {
    title: "Passkeys", subtitle: "Passwordless sign-in with your device (Face ID, fingerprint, security key).",
    name: "Name", namePlaceholder: "e.g. MacBook", add: "Add passkey", remove: "Remove", untitled: "Passkey",
    added: "Passkey added", addFailed: "Failed to add passkey", removed: "Passkey removed", removeFailed: "Failed to remove passkey",
    empty: "No passkeys yet.", created: "Created", total: "{count} passkeys",
  },
  acceptInvitation: {
    title: "Organization invitation", pending: "Accepting your invitation…",
    ok: "You have joined the organization.", error: "This invitation is invalid or has expired.",
    goToOrgs: "Go to organizations",
  },
  organizations: {
    title: "Organizations", subtitle: "Multi-tenant teams. Create organizations and invite members.",
    create: "New organization", createTitle: "Create organization", name: "Name", slug: "Slug",
    created: "Created", delete: "Delete", cancel: "Cancel", empty: "No organizations yet.", total: "{count} organizations",
    submit: "Create", createdMsg: "Organization created", deletedMsg: "Organization deleted", actionFailed: "Action failed",
    manage: "Manage", membersDesc: "Members and pending invitations.", members: "Members", pending: "Pending invitations",
    parent: "Parent organization", noParent: "None (top level)", managers: "Managers", managersHint: "Existing users to add as managers (any number).",
    inviteEmail: "Invite by email", invite: "Invite", invited: "Invitation sent", remove: "Remove", cancelInvite: "Cancel",
  },
  consent: {
    title: "Authorize access", subtitle: "An application is requesting access to your account.",
    requests: "It will be able to access:", allow: "Allow", deny: "Deny",
  },
  apiKeys: {
    title: "API keys", subtitle: "Personal keys for programmatic access. Send as an x-api-key header.",
    name: "Name", namePlaceholder: "e.g. CI pipeline", create: "Create key",
    keyColumn: "Key", created: "Created", untitled: "Untitled", revoke: "Revoke",
    revoked: "Key revoked", revokeFailed: "Failed to revoke key", empty: "No API keys yet.", total: "{count} API keys",
    createdTitle: "API key created", createdDesc: "Copy it now — you will not be able to see it again.",
    copy: "Copy", copied: "Copied to clipboard", done: "Done",
  },
  general: {
    tab: "General",
    brandingTitle: "Branding", brandingDesc: "The site name and icon shown in the browser and across the app.",
    siteName: "Site name", siteNamePlaceholder: "My App",
    siteNameHint: "Used as the browser tab title and wherever the app name appears.",
    favicon: "Browser icon (favicon)",
    faviconHint: "SVG (recommended) or a square PNG 512×512, ≤ 1 MB. Applied to every page.",
    iconSaved: "Icon updated.", iconError: "Failed to upload the icon.", iconTooBig: "Icon must be 1 MB or smaller.",
    brandColor: "Brand color",
    infoTitle: "Site info", infoDesc: "Optional details used in meta tags, the footer, and links.",
    description: "Description", descriptionPlaceholder: "A short tagline for your site",
    supportEmail: "Support email", footerText: "Footer text",
    termsUrl: "Terms URL", privacyUrl: "Privacy URL",
    locale: "Default language", timezone: "Default timezone",
    opsTitle: "Operations",
    maintenance: "Maintenance mode", maintenanceDesc: "Show a maintenance page to non-admins.",
    allowSignup: "Allow public sign-up", allowSignupDesc: "Turn off to make the app invite-only.",
    save: "Save changes", saving: "Saving…", saved: "General settings saved.", saveError: "Failed to save settings.",
  },
  settings: {
    tab: "Authentication",
    title: "Settings", subtitle: "Which authentication features are enabled, and how they are configured.",
    authFeaturesTitle: "Authentication features", authFeaturesSubtitle: "Toggle sign-in methods and security features. Changes apply immediately.",
    serverConfigTitle: "Server configuration", serverConfigSubtitle: "Set through environment variables and applied at startup (read-only).",
    enabled: "Enabled", disabled: "Disabled", configuredVia: "Configured via {env}", manage: "Manage",
    saved: "Setting updated", saveFailed: "Failed to update setting",
    emailPassword: "Email & password", emailPasswordDesc: "Sign in with an email address and password.",
    emailVerification: "Email verification", emailVerificationDesc: "Require new sign-ups to confirm their address.",
    magicLink: "Magic link", magicLinkDesc: "Passwordless sign-in via an emailed link.",
    emailOtp: "Email one-time code", emailOtpDesc: "Passwordless sign-in with an emailed code.",
    username: "Username sign-in", usernameDesc: "Let users sign in with a username instead of an email.",
    multiSession: "Multi-account sessions", multiSessionDesc: "Let one browser stay signed into several accounts and switch between them.",
    phoneNumber: "Phone number", phoneNumberDesc: "Register and verify a phone number via SMS (configure a provider for real delivery).",
    apiKey: "API keys", apiKeyDesc: "Let users create personal API keys for programmatic access.",
    passkey: "Passkeys", passkeyDesc: "Let users register passkeys for passwordless sign-in.",
    organization: "Organizations", organizationDesc: "Multi-tenant organizations with members and email invitations.",
    oidcProvider: "OIDC provider", oidcProviderDesc: "Act as an identity provider so other apps can sign in with this one.",
    twoFactor: "Two-factor authentication", twoFactorDesc: "TOTP second factor with backup codes.",
    socialProviders: "Social providers", socialProvidersDesc: "OAuth sign-in (Google, GitHub).",
    breachCheck: "Breached-password check", breachCheckDesc: "Reject passwords found in known breaches (Have I Been Pwned).",
    accountDeletion: "Account deletion", accountDeletionDesc: "Let users delete their own account.",
    auditLog: "Audit log", auditLogDesc: "Record security-relevant actions.",
    signInTitle: "Sign-in methods", signInSubtitle: "How users authenticate. Toggle methods on/off; social providers open a popup for credentials.",
    emailTitle: "Email", emailSubtitle: "Outgoing mail (SMTP) and the email-verification policy.",
    securityTitle: "Security & policy", securitySubtitle: "Second factor, breached-password rejection, account deletion, and audit logging.",
    advancedTitle: "Advanced", advancedSubtitle: "API keys, organizations, and acting as an OIDC identity provider.",
    socialTitle: "Social login", socialSubtitle: "Paste OAuth credentials to enable sign-in with a provider. Applied immediately — no restart. Secrets are stored encrypted.",
    smtpTitle: "SMTP (email delivery)", smtpSubtitle: "Outgoing mail for sign-in links, verification, and invitations. Applied immediately.",
    google: "Google", github: "GitHub",
    clientId: "Client ID", clientSecret: "Client secret", redirectUri: "Redirect URI", secretSet: "•••••••• (saved — leave blank to keep)",
    save: "Save", cancel: "Cancel", configure: "Configure", notConfigured: "Not configured", configuredOff: "Configured (off)",
    socialDialogDesc: "Paste the OAuth client ID and secret from the provider's console, then enable it. Applied immediately.",
    smtpEnabled: "Enabled", smtpHost: "Host", smtpPort: "Port", smtpUser: "Username", smtpPass: "Password", smtpFrom: "From address", smtpSecure: "TLS (secure)",
    addProvider: "Add provider", provider: "Provider", remove: "Remove", smtpConfigure: "SMTP settings",
    edit: "Edit", close: "Close", back: "Back", noProviders: "No providers added yet.",
    socialCardDesc: "Sign in with Google, GitHub, Apple and other OAuth providers.",
  },
  dashboard: { title: "Dashboard", welcome: "Welcome back, {name}.", yourRole: "Your role", signedInAs: "Signed in as", unverifiedUsers: "Unverified users" },
  audit: { title: "Audit log", when: "When", actor: "Actor", action: "Action", target: "Target", ip: "IP", empty: "No audit entries.", loadFailed: "Failed to load audit log", total: "{count} entries", searchField: "Actor or target" },
  users: {
    title: "Users",
    search: "Search by email…",
    name: "Name",
    email: "Email",
    role: "Role",
    status: "Status",
    active: "Active",
    banned: "Banned",
    makeUser: "Make user",
    makeAdmin: "Make admin",
    ban: "Ban",
    unban: "Unban",
    empty: "No users.",
    total: "{count} users",
    previous: "Previous",
    next: "Next",
    roleSet: "Role set to {role}",
    userBanned: "User banned",
    userUnbanned: "User unbanned",
    loadFailed: "Failed to load users",
    actionFailed: "Action failed",
    addUser: "Add user",
    createTitle: "Create user",
    password: "Password",
    create: "Create",
    cancel: "Cancel",
    close: "Close",
    roleAdmin: "Admin",
    roleUser: "User",
    roleModerator: "Moderator",
    userCreated: "User created",
    setPassword: "Set password",
    newPassword: "New password",
    save: "Save",
    passwordSet: "Password updated",
    delete: "Delete",
    deleteTitle: "Delete user",
    deleteConfirm: "Delete {email}? This cannot be undone.",
    userDeleted: "User deleted",
    confirmPassword: "Confirm password",
    confirmNewPassword: "Confirm new password",
    passwordMismatch: "Passwords do not match",
    edit: "Edit",
    editTitle: "Edit user",
    userUpdated: "User updated",
    impersonate: "Impersonate",
    banTitle: "Ban user",
    banReason: "Reason (optional)",
    banExpiryDays: "Expires in (days, optional)",
    banExpiry: "Ban expires",
    banPermanent: "Permanent ban",
    joined: "Joined",
    stopImpersonating: "Stop impersonating",
    impersonatingAs: "Impersonating {email}",
    manage: "Manage",
    revokeSession: "Revoke",
    verified: "Verified",
    unverified: "Unverified",
    sendVerification: "Send verification email",
    verificationSent: "Verification email sent",
    markVerified: "Mark verified",
    markedVerified: "Marked as verified",
    sendResetEmail: "Send password reset email",
    resetEmailSent: "Password reset email sent",
    sendVerificationOnCreate: "Send verification email",
  },
  sessions: {
    title: "Active sessions",
    device: "Device",
    ip: "IP",
    since: "Since",
    revoke: "Revoke",
    unknown: "Unknown",
    empty: "No active sessions.",
    revoked: "Session revoked",
    loadFailed: "Failed to load sessions",
    revokeFailed: "Failed to revoke",
    status: "Status",
    current: "Current",
    signOutOthers: "Sign out other sessions",
    accountsTitle: "Signed-in accounts", switchAccount: "Switch", switchFailed: "Failed to switch account",
    othersRevoked: "Signed out other sessions",
    total: "{count} sessions",
  },
  adminSessions: {
    title: "User sessions",
    user: "User",
    device: "Device",
    ip: "IP",
    since: "Since",
    expires: "Expires",
    impersonated: "Impersonated",
    revoke: "Revoke session",
    revokeAll: "Revoke all for user",
    unknown: "Unknown",
    empty: "No active sessions.",
    revoked: "Session revoked",
    allRevoked: "All sessions revoked for user",
    loadFailed: "Failed to load sessions",
    total: "{count} sessions",
  },
  account: {
    title: "Account",
    profile: "Profile",
    name: "Name",
    username: "Username",
    phone: "Phone number", phoneCode: "Verification code", phoneSendCode: "Send code", phoneVerify: "Verify", phoneCodeSent: "Code sent", phoneVerified: "Phone verified",
    email: "Email",
    role: "Role",
    changePassword: "Change password",
    currentPassword: "Current password",
    newPassword: "New password",
    update: "Update password",
    updating: "Updating…",
    changed: "Password changed",
    changeFailed: "Failed to change password",
    nav: { profile: "Profile", security: "Security", connected: "Connected", sessions: "Sessions", apiKeys: "API keys", danger: "Danger zone" },
    twoFactorTitle: "Two-factor authentication",
    twoFactorDesc: "Add a one-time code from your authenticator app at sign-in.",
    twoFactorOn: "Enabled",
    twoFactorOff: "Disabled",
    enable: "Enable",
    disable: "Disable",
    password: "Password",
    scanHint: "Add this to your authenticator app, then enter the 6-digit code.",
    setupKey: "Setup key (otpauth URI)",
    backupCodes: "Backup codes — store them somewhere safe",
    code: "Verification code",
    verify: "Verify",
    twoFactorEnabled: "Two-factor enabled",
    twoFactorDisabled: "Two-factor disabled",
    connectedTitle: "Connected accounts",
    connectedDesc: "Link social accounts to sign in with them.",
    connect: "Connect",
    disconnect: "Disconnect",
    connected: "Connected",
    notConnected: "Not connected",
    disconnected: "Disconnected",
    dangerTitle: "Delete account",
    dangerDesc: "Permanently delete your account and all associated data.",
    deleteAccount: "Delete account",
    deleteAccountConfirm: "This permanently deletes your account and cannot be undone. Enter your password to confirm.",
    accountDeleted: "Account deleted",
    save: "Save changes",
    saved: "Profile updated",
    saveFailed: "Failed to save profile",
    saving: "Saving…",
    changeEmail: "Change email",
    emailChanged: "Email address updated",
    emailChangePending: "Check your current inbox to approve the change",
    verified: "Verified",
    unverified: "Unverified",
  },
  // Modules add their i18n blocks here.
  // podokit:begin:messages-en
  // podokit:end:messages-en
};

export type Messages = typeof en;

const ko: Messages = {
  common: { appName: "관리자" },
  landing: { title: "환영합니다", subtitle: "앱의 홈 페이지입니다. 원하는 내용으로 교체하세요 — 관리자 기능은 /admin 에 있습니다.", openAdmin: "관리자 열기" },
  footer: { support: "고객지원", terms: "이용약관", privacy: "개인정보처리방침" },
  maintenance: { title: "점검 중", subtitle: "사이트를 일시적으로 사용할 수 없습니다. 잠시 후 다시 확인해 주세요.", adminHint: "관리자는 로그인하여 사이트를 관리할 수 있습니다.", signIn: "관리자 로그인" },
  language: { label: "언어" },
  toolbar: { filter: "필터", search: "검색", searchButton: "검색", all: "전체" },
  theme: { toggle: "테마 전환", light: "라이트", dark: "다크", system: "시스템" },
  auth: {
    signInTitle: "로그인",
    signInDesc: "계속하려면 로그인하세요.",
    email: "이메일",
    emailOrUsername: "이메일 또는 사용자명",
    password: "비밀번호",
    forgot: "비밀번호 찾기",
    signIn: "로그인",
    signingIn: "로그인 중…",
    magicLinkButton: "로그인 링크 이메일로 받기",
    passkeyButton: "패스키 사용",
    magicLinkSent: "이메일의 로그인 링크를 확인하세요.",
    magicLinkNeedsEmail: "먼저 이메일을 입력하세요.",
    otpButton: "코드 이메일로 받기", otpCode: "일회용 코드", otpVerify: "코드 확인",
    noAccount: "계정이 없으신가요?",
    signUp: "회원가입",
    signInFailed: "로그인에 실패했습니다",
    createTitle: "회원가입",
    createDesc: "가입하고 시작하세요.",
    name: "이름",
    create: "계정 만들기",
    creating: "생성 중…",
    haveAccount: "이미 계정이 있으신가요?",
    signUpFailed: "회원가입에 실패했습니다",
    resetTitle: "비밀번호 재설정",
    resetDesc: "이메일로 재설정 링크를 보내드립니다.",
    sendReset: "재설정 링크 보내기",
    sending: "전송 중…",
    resetSent: "해당 이메일이 존재하면 재설정 링크가 전송됩니다.",
    backToSignIn: "로그인으로 돌아가기",
    requestFailed: "요청에 실패했습니다",
    newTitle: "새 비밀번호 설정",
    newPassword: "새 비밀번호",
    updatePassword: "비밀번호 변경",
    updating: "변경 중…",
    missingToken: "재설정 토큰이 없거나 유효하지 않습니다.",
    verifyTitle: "이메일 인증",
    verifyDesc: "{email} 주소로 인증 링크를 보냈습니다. 링크를 열어 계정을 활성화하세요.",
    verifyDescNoEmail: "새 인증 링크를 받을 이메일을 입력하세요.",
    verifySent: "인증 메일을 보냈습니다 — 받은편지함을 확인하세요.",
    verifyLinkError: "인증 링크가 유효하지 않거나 만료되었습니다. 아래에서 다시 요청하세요.",
    resendVerification: "인증 메일 다시 보내기",
    emailNotVerified: "로그인 전에 이메일을 인증해 주세요.",
    resetFailed: "재설정에 실패했습니다",
  },
  nav: { overview: "개요", users: "회원", sessions: "세션", organizations: "조직", audit: "감사 로그", account: "계정", settings: "설정", home: "홈으로 돌아가기", signOut: "로그아웃" },
  passkeys: {
    title: "패스키", subtitle: "기기로 비밀번호 없이 로그인(Face ID, 지문, 보안 키).",
    name: "이름", namePlaceholder: "예: MacBook", add: "패스키 추가", remove: "삭제", untitled: "패스키",
    added: "패스키를 추가했습니다", addFailed: "패스키 추가에 실패했습니다", removed: "패스키를 삭제했습니다", removeFailed: "패스키 삭제에 실패했습니다",
    empty: "아직 패스키가 없습니다.", created: "생성일", total: "패스키 {count}개",
  },
  acceptInvitation: {
    title: "조직 초대", pending: "초대를 수락하는 중…",
    ok: "조직에 합류했습니다.", error: "유효하지 않거나 만료된 초대입니다.",
    goToOrgs: "조직으로 이동",
  },
  organizations: {
    title: "조직", subtitle: "멀티테넌트 팀. 조직을 만들고 멤버를 초대합니다.",
    create: "새 조직", createTitle: "조직 만들기", name: "이름", slug: "슬러그",
    created: "생성일", delete: "삭제", cancel: "취소", empty: "아직 조직이 없습니다.", total: "조직 {count}개",
    submit: "만들기", createdMsg: "조직을 만들었습니다", deletedMsg: "조직을 삭제했습니다", actionFailed: "작업에 실패했습니다",
    manage: "관리", membersDesc: "멤버와 대기 중인 초대.", members: "멤버", pending: "대기 중 초대",
    parent: "상위 조직", noParent: "없음(최상위)", managers: "매니저", managersHint: "매니저로 추가할 기존 사용자(여러 명 가능).",
    inviteEmail: "이메일로 초대", invite: "초대", invited: "초대를 보냈습니다", remove: "제거", cancelInvite: "취소",
  },
  consent: {
    title: "접근 승인", subtitle: "한 애플리케이션이 계정 접근을 요청합니다.",
    requests: "접근 가능 범위:", allow: "허용", deny: "거부",
  },
  apiKeys: {
    title: "API 키", subtitle: "프로그래밍 방식 접근용 개인 키. x-api-key 헤더로 전송합니다.",
    name: "이름", namePlaceholder: "예: CI 파이프라인", create: "키 생성",
    keyColumn: "키", created: "생성일", untitled: "제목 없음", revoke: "폐기",
    revoked: "키를 폐기했습니다", revokeFailed: "키 폐기에 실패했습니다", empty: "아직 API 키가 없습니다.", total: "API 키 {count}개",
    createdTitle: "API 키 생성됨", createdDesc: "지금 복사하세요 — 다시 볼 수 없습니다.",
    copy: "복사", copied: "클립보드에 복사됨", done: "완료",
  },
  general: {
    tab: "일반",
    brandingTitle: "브랜딩", brandingDesc: "브라우저와 앱 전반에 표시되는 사이트 이름과 아이콘입니다.",
    siteName: "사이트 이름", siteNamePlaceholder: "My App",
    siteNameHint: "브라우저 탭 제목과 앱 이름이 쓰이는 곳에 사용됩니다.",
    favicon: "브라우저 아이콘 (favicon)",
    faviconHint: "SVG(권장) 또는 정사각 PNG 512×512, 1 MB 이하. 모든 페이지에 적용됩니다.",
    iconSaved: "아이콘을 변경했습니다.", iconError: "아이콘 업로드에 실패했습니다.", iconTooBig: "아이콘은 1 MB 이하여야 합니다.",
    brandColor: "브랜드 색상",
    infoTitle: "사이트 정보", infoDesc: "메타 태그·푸터·링크에 쓰이는 선택 항목입니다.",
    description: "설명", descriptionPlaceholder: "사이트를 한 줄로 소개",
    supportEmail: "지원 이메일", footerText: "푸터 문구",
    termsUrl: "약관 URL", privacyUrl: "개인정보 URL",
    locale: "기본 언어", timezone: "기본 시간대",
    opsTitle: "운영",
    maintenance: "유지보수 모드", maintenanceDesc: "관리자 외 사용자에게 점검 페이지를 표시합니다.",
    allowSignup: "공개 가입 허용", allowSignupDesc: "끄면 초대 전용으로 전환됩니다.",
    save: "변경 저장", saving: "저장 중…", saved: "일반 설정을 저장했습니다.", saveError: "설정 저장에 실패했습니다.",
  },
  settings: {
    tab: "인증",
    title: "설정", subtitle: "활성화된 인증 기능과 구성 방법입니다.",
    authFeaturesTitle: "인증 기능", authFeaturesSubtitle: "로그인 수단과 보안 기능을 켜고 끕니다. 변경은 즉시 적용됩니다.",
    serverConfigTitle: "서버 구성", serverConfigSubtitle: "환경변수로 설정되어 시작 시 적용됩니다(읽기 전용).",
    enabled: "활성", disabled: "비활성", configuredVia: "{env} 로 구성", manage: "관리",
    saved: "설정을 변경했습니다", saveFailed: "설정 변경에 실패했습니다",
    emailPassword: "이메일·비밀번호", emailPasswordDesc: "이메일과 비밀번호로 로그인.",
    emailVerification: "이메일 인증", emailVerificationDesc: "신규 가입 시 이메일 확인 요구.",
    magicLink: "매직 링크", magicLinkDesc: "이메일 링크로 비밀번호 없이 로그인.",
    emailOtp: "이메일 일회용 코드", emailOtpDesc: "이메일로 받은 코드로 비밀번호 없이 로그인.",
    username: "사용자명 로그인", usernameDesc: "이메일 대신 사용자명으로 로그인.",
    multiSession: "다중 계정 세션", multiSessionDesc: "한 브라우저에서 여러 계정에 로그인하고 전환.",
    phoneNumber: "전화번호", phoneNumberDesc: "SMS로 전화번호 등록·인증(실발송은 프로바이더 연동 필요).",
    apiKey: "API 키", apiKeyDesc: "프로그래밍 방식 접근을 위한 개인 API 키 발급을 허용.",
    passkey: "패스키", passkeyDesc: "비밀번호 없는 로그인을 위한 패스키 등록을 허용.",
    organization: "조직", organizationDesc: "멤버와 이메일 초대를 갖춘 멀티테넌트 조직.",
    oidcProvider: "OIDC 제공자", oidcProviderDesc: "다른 앱이 이 앱으로 로그인하도록 신원 제공자 역할.",
    twoFactor: "2단계 인증", twoFactorDesc: "TOTP 2차 인증 + 백업 코드.",
    socialProviders: "소셜 로그인", socialProvidersDesc: "OAuth 로그인 (Google, GitHub).",
    breachCheck: "유출 비밀번호 검사", breachCheckDesc: "유출된 비밀번호 거부 (Have I Been Pwned).",
    accountDeletion: "계정 삭제", accountDeletionDesc: "사용자가 자신의 계정을 삭제.",
    auditLog: "감사 로그", auditLogDesc: "보안 관련 동작 기록.",
    signInTitle: "로그인 수단", signInSubtitle: "사용자가 인증하는 방법. 각 수단을 켜고 끄며, 소셜 로그인은 팝업에서 자격증명을 입력합니다.",
    emailTitle: "이메일", emailSubtitle: "메일 발송(SMTP) 설정과 이메일 인증 정책.",
    securityTitle: "보안·정책", securitySubtitle: "2단계 인증, 유출 비밀번호 거부, 계정 삭제, 감사 로그.",
    advancedTitle: "고급", advancedSubtitle: "API 키, 조직, OIDC 공급자(자체 IdP) 역할.",
    socialTitle: "소셜 로그인", socialSubtitle: "OAuth 자격증명을 붙여넣으면 해당 provider 로그인이 켜집니다. 재시작 없이 즉시 적용되며, 비밀은 암호화 저장됩니다.",
    smtpTitle: "SMTP(이메일 발송)", smtpSubtitle: "로그인 링크·인증·초대 발송용. 즉시 적용됩니다.",
    google: "Google", github: "GitHub",
    clientId: "Client ID", clientSecret: "Client secret", redirectUri: "Redirect URI", secretSet: "•••••••• (저장됨 — 비우면 유지)",
    save: "저장", cancel: "취소", configure: "설정", notConfigured: "미설정", configuredOff: "설정됨(꺼짐)",
    socialDialogDesc: "provider 콘솔의 OAuth client ID와 secret을 붙여넣고 사용을 켜세요. 즉시 적용됩니다.",
    smtpEnabled: "사용", smtpHost: "호스트", smtpPort: "포트", smtpUser: "사용자", smtpPass: "비밀번호", smtpFrom: "발신 주소", smtpSecure: "TLS(보안)",
    addProvider: "공급자 추가", provider: "공급자", remove: "삭제", smtpConfigure: "SMTP 설정",
    edit: "편집", close: "닫기", back: "뒤로", noProviders: "아직 추가된 공급자가 없습니다.",
    socialCardDesc: "Google, GitHub, Apple 등 OAuth 공급자로 로그인.",
  },
  dashboard: { title: "대시보드", welcome: "{name}님, 환영합니다.", yourRole: "내 권한", signedInAs: "로그인 계정", unverifiedUsers: "미인증 사용자" },
  audit: { title: "감사 로그", when: "시각", actor: "수행자", action: "동작", target: "대상", ip: "IP", empty: "감사 기록이 없습니다.", loadFailed: "감사 로그를 불러오지 못했습니다", total: "항목 {count}개", searchField: "수행자·대상" },
  users: {
    title: "회원",
    search: "이메일로 검색…",
    name: "이름",
    email: "이메일",
    role: "권한",
    status: "상태",
    active: "활성",
    banned: "차단됨",
    makeUser: "일반 사용자로",
    makeAdmin: "관리자로",
    ban: "차단",
    unban: "차단 해제",
    empty: "회원이 없습니다.",
    total: "회원 {count}명",
    previous: "이전",
    next: "다음",
    roleSet: "권한을 {role}(으)로 변경했습니다",
    userBanned: "회원을 차단했습니다",
    userUnbanned: "차단을 해제했습니다",
    loadFailed: "회원 목록을 불러오지 못했습니다",
    actionFailed: "작업에 실패했습니다",
    addUser: "사용자 추가",
    createTitle: "사용자 생성",
    password: "비밀번호",
    create: "생성",
    cancel: "취소",
    close: "닫기",
    roleAdmin: "관리자",
    roleUser: "사용자",
    roleModerator: "중재자",
    userCreated: "사용자를 생성했습니다",
    setPassword: "비밀번호 설정",
    newPassword: "새 비밀번호",
    save: "저장",
    passwordSet: "비밀번호를 변경했습니다",
    delete: "삭제",
    deleteTitle: "사용자 삭제",
    deleteConfirm: "{email} 사용자를 삭제할까요? 되돌릴 수 없습니다.",
    userDeleted: "사용자를 삭제했습니다",
    confirmPassword: "비밀번호 확인",
    confirmNewPassword: "새 비밀번호 확인",
    passwordMismatch: "비밀번호가 일치하지 않습니다",
    edit: "편집",
    editTitle: "사용자 편집",
    userUpdated: "사용자를 수정했습니다",
    impersonate: "이 사용자로 로그인",
    banTitle: "사용자 차단",
    banReason: "사유 (선택)",
    banExpiryDays: "만료 (일, 선택)",
    banExpiry: "차단 만료",
    banPermanent: "영구 차단",
    joined: "가입일",
    stopImpersonating: "대리 로그인 종료",
    impersonatingAs: "{email} 사용자로 대리 로그인 중",
    manage: "관리",
    revokeSession: "종료",
    verified: "인증됨",
    unverified: "미인증",
    sendVerification: "인증 메일 보내기",
    verificationSent: "인증 메일을 보냈습니다",
    markVerified: "인증됨으로 표시",
    markedVerified: "인증 처리했습니다",
    sendResetEmail: "비밀번호 재설정 메일 보내기",
    resetEmailSent: "재설정 메일을 보냈습니다",
    sendVerificationOnCreate: "인증 메일 보내기",
  },
  sessions: {
    title: "활성 세션",
    device: "기기",
    ip: "IP",
    since: "시작",
    revoke: "종료",
    unknown: "알 수 없음",
    empty: "활성 세션이 없습니다.",
    revoked: "세션을 종료했습니다",
    loadFailed: "세션을 불러오지 못했습니다",
    revokeFailed: "세션 종료에 실패했습니다",
    status: "상태",
    current: "현재",
    signOutOthers: "다른 세션 모두 종료",
    accountsTitle: "로그인된 계정", switchAccount: "전환", switchFailed: "계정 전환에 실패했습니다",
    othersRevoked: "다른 세션을 모두 종료했습니다",
    total: "세션 {count}개",
  },
  adminSessions: {
    title: "사용자 세션",
    user: "사용자",
    device: "기기",
    ip: "IP",
    since: "시작",
    expires: "만료",
    impersonated: "임퍼스네이트",
    revoke: "세션 종료",
    revokeAll: "사용자 세션 모두 종료",
    unknown: "알 수 없음",
    empty: "활성 세션이 없습니다.",
    revoked: "세션을 종료했습니다",
    allRevoked: "사용자의 세션을 모두 종료했습니다",
    loadFailed: "세션을 불러오지 못했습니다",
    total: "세션 {count}개",
  },
  account: {
    title: "계정",
    profile: "프로필",
    name: "이름",
    username: "사용자명",
    phone: "전화번호", phoneCode: "인증 코드", phoneSendCode: "코드 전송", phoneVerify: "인증", phoneCodeSent: "코드를 전송했습니다", phoneVerified: "전화번호 인증됨",
    email: "이메일",
    role: "권한",
    changePassword: "비밀번호 변경",
    currentPassword: "현재 비밀번호",
    newPassword: "새 비밀번호",
    update: "비밀번호 변경",
    updating: "변경 중…",
    changed: "비밀번호를 변경했습니다",
    changeFailed: "비밀번호 변경에 실패했습니다",
    nav: { profile: "프로필", security: "보안", connected: "연결", sessions: "세션", apiKeys: "API 키", danger: "위험 영역" },
    twoFactorTitle: "2단계 인증",
    twoFactorDesc: "로그인 시 인증 앱의 일회용 코드를 추가로 요구합니다.",
    twoFactorOn: "사용 중",
    twoFactorOff: "사용 안 함",
    enable: "사용",
    disable: "해제",
    password: "비밀번호",
    scanHint: "인증 앱에 등록한 뒤 6자리 코드를 입력하세요.",
    setupKey: "설정 키 (otpauth URI)",
    backupCodes: "백업 코드 — 안전한 곳에 보관하세요",
    code: "인증 코드",
    verify: "확인",
    twoFactorEnabled: "2단계 인증을 사용합니다",
    twoFactorDisabled: "2단계 인증을 해제했습니다",
    connectedTitle: "연결된 계정",
    connectedDesc: "소셜 계정을 연결하면 해당 계정으로 로그인할 수 있습니다.",
    connect: "연결",
    disconnect: "연결 해제",
    connected: "연결됨",
    notConnected: "연결 안 됨",
    disconnected: "연결을 해제했습니다",
    dangerTitle: "계정 삭제",
    dangerDesc: "계정과 모든 관련 데이터를 영구히 삭제합니다.",
    deleteAccount: "계정 삭제",
    deleteAccountConfirm: "계정이 영구히 삭제되며 되돌릴 수 없습니다. 확인하려면 비밀번호를 입력하세요.",
    accountDeleted: "계정을 삭제했습니다",
    save: "변경 저장",
    saved: "프로필을 저장했습니다",
    saveFailed: "프로필 저장에 실패했습니다",
    saving: "저장 중…",
    changeEmail: "이메일 변경",
    emailChanged: "이메일 주소를 변경했습니다",
    emailChangePending: "현재 메일함에서 변경을 승인해 주세요",
    verified: "인증됨",
    unverified: "미인증",
  },
  // Modules add their i18n blocks here.
  // podokit:begin:messages-ko
  // podokit:end:messages-ko
};

export const messages: Record<Locale, Messages> = { en, ko };

export function resolveLocale(value: string | undefined | null): Locale {
  return LOCALES.includes(value as Locale) ? (value as Locale) : defaultLocale;
}
