Files
chat/frontend/src/lib/i18n.ts
T
2026-09-24 10:33:43 +02:00

3501 lines
161 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useSyncExternalStore } from "react";
/**
* Platform i18n — TypeScript dictionaries (NOT JSON).
* English is the source of truth: `StringKey = keyof typeof en`, and every
* other language is typed `Record<StringKey, string>`, so a missing
* translation is a COMPILE error. Fallback chain: current lang -> English.
*/
export const LANGS = [
{ id: "en", label: "English" },
{ id: "es", label: "Español" },
{ id: "fr", label: "Français" },
{ id: "ru", label: "Русский" },
{ id: "it", label: "Italiano" },
{ id: "pt", label: "Português" },
] as const;
export type LangId = (typeof LANGS)[number]["id"];
const en = {
"common.close": "Close",
"common.cancel": "Cancel",
"common.save": "Save",
"common.done": "Done",
"common.copy": "Copy",
"common.copied": "Copied",
"common.create": "Create",
"common.delete": "Delete",
"common.loading": "Loading…",
"common.saving": "Saving…",
"common.username": "Username",
"common.displayName": "Display name",
"common.select": "Select…",
"common.theme": "Theme",
"common.themeAuto": "Auto",
"common.themeAutoFull": "Auto (follows system)",
"common.themeSunset": "Sunset",
"common.themeSunsetFull": "Sunset (follows local time)",
"common.light": "Light",
"common.dark": "Dark",
"common.saveFailed": "Save failed",
"common.loadFailed": "Load failed",
"common.deleteFailed": "Delete failed",
"common.backToLogin": "Back to login",
"loading.tagline": "Preparing your chats",
"login.welcome": "Welcome back",
"login.subtitle": "Sign in to KisAssistant to continue",
"login.usernamePh": "Username",
"login.keyPh": "Access key",
"login.failed": "Login failed",
"login.unlock": "Unlock",
"login.newHere": "New here?",
"login.register": "Register",
"login.regTipOn": "Create an account",
"login.regTipOff": "Registration currently disabled on this platform",
"login.requestAccess": "Request access",
"login.forgot": "Forgot your access key?",
"login.perk1": "Private by design — no cookies, no tracking",
"login.perk2": "Your own models, streamed in real time",
"login.adminNotePre": "Admin key lives in the server ",
"login.adminNotePost": "; user keys are issued by the admin.",
"login.totpIntro": "Two-factor for @{user} — enter the 6-digit code from your authenticator app.",
"login.totpAria": "Authenticator code",
"login.totpInvalid": "Invalid code",
"login.verify": "Verify",
"sidebar.newChat": "New chat",
"sidebar.collapse": "Collapse sidebar",
"sidebar.closeDrawer": "Close chats",
"sidebar.searchPh": "Search chats…",
"sidebar.searchAria": "Search conversations",
"sidebar.clearSearch": "Clear search",
"sidebar.searching": "Searching…",
"sidebar.noMatch": "No match for “{q}”.",
"sidebar.youPrefix": "you: ",
"sidebar.emptyA": "No conversations yet.",
"sidebar.emptyB": "Start a new chat above.",
"sidebar.rename": "Rename",
"sidebar.topic": "Set topic",
"sidebar.share": "Share publicly",
"sidebar.delete": "Delete",
"sidebar.convOptions": "Conversation options",
"sidebar.admin": "admin",
"sidebar.adminCenter": "Admin Center",
"sidebar.adminCenterTip": "Open the Admin Center",
"sidebar.settingsTip": "Profile & settings",
"sidebar.logout": "Log out",
"sidebar.archive": "Archive",
"chat.expand": "Expand sidebar",
"chat.openNav": "Open chats",
"chat.modelAria": "Model",
"chat.noModels": "No models",
"chat.selectModel": "Select model…",
"chat.personalTag": "personal key",
"toast.chatDeleted": "Chat “{title}” deleted",
"toast.chatArchived": "Chat “{title}” archived",
"toast.chatUnarchived": "Chat “{title}” unarchived",
"toast.modelChanged": "Model: {label}",
"toast.themeChanged": "Theme changed",
"toast.accentChanged": "Accent color changed",
"toast.unshared": "Share link removed",
"toast.settingsSaved": "Settings saved",
"toast.convUpdated": "Conversation “{title}” updated",
"chat.you": "You",
"chat.greet": "How can I help, {name}?",
"chat.greetSub": "Pick a model, then type below. Markdown is supported.",
"chat.thinking": "Thinking…",
"chat.placeholder": "Message KisAssistant…",
"chat.send": "Send",
"chat.attachTip": "Attach a file",
"chat.removeAttach": "Remove {name}",
"chat.ocrOpt": "Transcribe image",
"chat.unavailable": "(unavailable)",
"chat.ocrHint":
"JPG, PNG, WEBP — OCR on the server, you review the text first",
"chat.textOpt": "Attach text file",
"chat.textHint": "TXT or Markdown, max 500KB",
"chat.attachNote":
"Uploads go through platform tools only. Images are sent to the model as reviewed text — never as raw images.",
"chat.wiki": "Wiki & docs",
"attach.tooBigImg": "Image too large (max 5MB).",
"attach.tooBigText": "Text file too large (max 500KB).",
"attach.uploadFailed": "Upload failed",
"attach.kindOcr": "image transcription",
"attach.kindText": "text file",
"attach.tpl": "[attached {kind}: {name}]",
"attach.chatError": "**Error:** the model did not respond. Try again.",
"dlg.editConv": "Edit conversation",
"dlg.fTitle": "Title",
"dlg.fTopic": "Topic",
"dlg.topicHint": "A short theme tag, e.g. cooking, rust, travel.",
"dlg.noTopic": "No topic",
"dlg.recoverTitle": "Recover access key",
"dlg.recoverIntro":
"Enter your username. You'll receive a link that issues a fresh key (the old one stops working).",
"dlg.sendLink": "Send reset link",
"dlg.reqFailed": "Request failed",
"dlg.recoverSent":
"If @{user} exists and has a recovery email, a reset link is on its way{fromPart} (valid 60 minutes, single use).",
"dlg.recoverSentFrom": " from {from}",
"dlg.spamNote":
"Check your inbox — and your spam folder, the message may have landed there.",
"dlg.noMailNote":
"Nothing arrives? Then no recovery email is set on your account and the reset is not possible — please contact the site administrator.",
"dlg.registerTitle": "Create an account",
"dlg.regWelcome":
"Welcome, @{user}! Your access key — copy it now, it won't be shown again.",
"dlg.regContinue": "Copy & continue to login",
"dlg.regFailed": "Registration failed",
"dlg.emailOpt": "Email (optional, for key recovery)",
"dlg.shareTitle": "Share publicly",
"dlg.shareCreating": "Creating public link…",
"dlg.shareIntro":
"Anyone with this link can read {title}. No login required.",
"dlg.unshare": "Unshare",
"dlg.reviewOcr": "Review transcription",
"dlg.reviewText": "Review text attachment",
"dlg.transcribing": "Transcribing the image on the server (OCR)…",
"dlg.uploadingTools": "Uploading through platform tools…",
"dlg.ocrExpl":
"The image was transcribed to text on the server — the model receives this text, never the image. Fix any reading mistakes below, then attach.",
"dlg.textExpl":
"The file was uploaded through platform tools. Its text content is attached to your message. Edit below if needed, then attach.",
"dlg.truncWarn":
"Transcription truncated to the server limit — the end is missing.",
"dlg.attachBtn": "Attach to message",
"dlg.chars": "{n} chars",
"settings.title": "Settings",
"settings.searchPh": "Search settings…",
"settings.searchAria": "Search settings",
"settings.clearSearch": "Clear settings search",
"settings.noMatch": "No settings match “{q}”.",
"settings.profile": "Profile",
"settings.appearance": "Appearance",
"settings.features": "Features",
"settings.avatarUpload": "Avatar upload",
"settings.dropIdle": "Drop an image or click to upload",
"settings.dropActive": "Drop it!",
"settings.uploading": "Uploading…",
"settings.avatarHint": "jpg · png · webp — max 5MB — 5 changes per 2h",
"settings.username": "Username",
"settings.usernameHint":
"Login name. 2–32 chars: lowercase letters, digits, . _ -. Takes effect immediately.",
"settings.email": "Recovery email",
"settings.emailHint":
"Optional. Used only to send you a fresh access key if you lose it.",
"settings.accent": "Accent color",
"settings.accentHint": "Applied instantly, saved on this device.",
"settings.customColor": "Custom color",
"settings.customAria": "Custom accent color",
"settings.accentAria": "Accent: {label}",
"settings.featHint":
"Turn composer capabilities on or off. Applied instantly, saved on this device.",
"settings.providers": "Providers",
"providers.intro":
"Connect your own API keys. Models from connected providers show up in the model menu at the top.",
"providers.hint":
"Keys stay on this server and are never shown again — only the last 4 characters. Usage is billed to your own provider account, and the admin model policy still applies.",
"providers.connected": "Connected",
"providers.notConnected": "Not connected",
"providers.keyPh": "Paste API key…",
"providers.saveKey": "Save key",
"providers.removeKey": "Remove",
"providers.replaceKey": "Replace",
"providers.getKey": "Get a key",
"providers.keySaved": "Key saved — its models are now in the menu.",
"providers.keyRemoved": "Key removed.",
"providers.invalidKey": "That key looks invalid (8–256 characters, no spaces).",
"providers.loadFailed": "Could not load providers.",
"accent.preset.emerald": "Emerald",
"accent.preset.rose": "Rose",
"accent.preset.blue": "Blue",
"accent.preset.violet": "Violet",
"accent.preset.amber": "Yellow",
"accent.preset.orange": "Orange",
"accent.preset.teal": "Teal",
"accent.preset.pink": "Pink",
"feat.thinking.label": "Thinking",
"feat.thinking.hint":
"Ask the model to reason step-by-step before answering.",
"feat.attachments.label": "Attachments",
"feat.attachments.hint":
"Attach images (OCR transcription) and text files to messages.",
"feat.deepSearch.label": "Deep search",
"feat.deepSearch.hint":
"Let the assistant search the web for fresh sources. Coming soon.",
"feat.soon": "(soon)",
"admin.title": "Accounts",
"admin.intro":
"No-KYC accounts: you create a username, hand the access key to its owner once. Keys are stored hashed — regenerate to rotate.",
"admin.keyOnce": "Key for @{user} — shown once, copy it now:",
"admin.newAccount": "New account",
"admin.email": "Email (recovery)",
"admin.createFailed": "Create failed",
"admin.regenFailed": "Regenerate failed",
"admin.deleteFailed": "Delete failed",
"admin.loadFailed": "Load failed",
"admin.searchPh": "Search accounts…",
"admin.searchAria": "Search accounts",
"admin.sortAria": "Sort accounts",
"admin.filterAria": "Filter accounts",
"admin.sortNewest": "Newest first",
"admin.sortOldest": "Oldest first",
"admin.sortAz": "A → Z",
"admin.sortZa": "Z → A",
"admin.filterAll": "All accounts",
"admin.filterWith": "With recovery email",
"admin.filterNo": "No recovery email",
"admin.countMany": "{total} accounts · page {page} of {pages}",
"admin.countOne": "{total} account · page {page} of {pages}",
"admin.noEmail": "no recovery email",
"admin.editProfile": "Edit profile",
"admin.regenKey": "Regenerate key (revokes old sessions)",
"admin.deleteAccount": "Delete account",
"admin.deleteTitle": "Delete @{user}?",
"admin.deleteMsg":
"This permanently removes the account, all its conversations and its shares.",
"admin.prevPage": "Previous page",
"admin.nextPage": "Next page",
"ollama.models": "Ollama models",
"ollama.desc":
"Download models from the Ollama library to your Ollama host, or remove local ones. Admin only.",
"ollama.pulling": "Pulling {name}",
"ollama.customTag": "Custom model tag",
"ollama.customHint": "e.g. llama3.2:3b, or a full library name",
"ollama.pull": "Pull",
"ollama.installed": "Installed ({n})",
"ollama.noneYet": "No local Ollama models yet.",
"ollama.catalog": "Catalog",
"ollama.delTitle": "Delete {name}?",
"ollama.delMsg":
"The model is removed from the Ollama host. Pull it again anytime.",
"ollama.contacting": "Contacting Ollama…",
"ollama.pullingSt": "Pulling…",
"ollama.doneSt": "Done",
"ollama.pullFailed": "Pull failed",
"ollama.delTip": "Delete {name}",
"ollama.sizeAria": "{name} size",
"ollama.cat.llama3_2": "Meta's compact everyday model",
"ollama.cat.llama3_1": "Meta's general-purpose workhorse",
"ollama.cat.qwen2_5": "Alibaba's multilingual all-rounder",
"ollama.cat.gemma2": "Google's efficient open model",
"ollama.cat.mistral": "Mistral 7B — fast and capable",
"ollama.cat.phi3": "Microsoft's small research model",
"ollama.cat.deepseek_r1": "Reasoning model (chain-of-thought)",
"ollama.cat.codellama": "Code completion and chat",
"ollama.cat.llava": "Vision model (image understanding)",
"ollama.cat.nomic_embed_text": "Text embeddings",
"center.title": "Admin Center",
"center.back": "Back to chat",
"center.tabAccounts": "Accounts",
"center.tabFeatures": "Features",
"center.tabMail": "Mail",
"center.tabModels": "Models",
"models.title": "Models",
"models.desc": "Enable or limit each model. Disabled models disappear from the picker; limits apply per user (admins bypass them).",
"models.refresh": "Refresh",
"models.refreshAria": "Refresh models",
"models.enabled": "Enabled",
"models.hourly": "per hour",
"models.daily": "per day",
"models.unlimited": "Unlimited",
"models.ollamaTitle": "Ollama library",
"models.ollamaDesc": "Pull or remove local models.",
"models.empty": "No models available.",
"models.saveFailed": "Could not save",
"models.connTitle": "Ollama connectivity",
"models.connDesc": "Live status of the Ollama host: reachability, version, latency and installed models.",
"models.connOnline": "Online",
"models.connOffline": "Offline",
"models.connDisabledState": "Disabled",
"models.connCheck": "Check now",
"models.connCheckAria": "Check Ollama connectivity now",
"models.connHost": "Host",
"models.connVersion": "Version",
"models.connLatency": "Latency",
"models.connModels": "Models",
"models.connEmpty": "No models on the Ollama host yet — pull one from the library below.",
"models.connHint": "Make sure Ollama is running and OLLAMA_HOST points at it.",
"center.locked": "Admins only",
"center.lockedSub": "Log in with the admin account to open the Admin Center.",
"center.regTitle": "Public registration",
"center.regDesc":
"Show the Register button on the login page. Off = admin-created accounts only. Turning it on retires the wishlist below.",
"center.accTitle": "Access requests (wishlist)",
"center.accDescOn":
"Unavailable while public registration is on — it replaces the wishlist.",
"center.accDescOff":
"Show Request access on the login page. Visitors reserve a username and plead their case; you triage them in the Access tab.",
"center.ocrTitle": "OCR tool",
"center.ocrDesc":
"Server-side image transcription for attachments. Requires the tesseract binary.",
"center.reportsTitle": "Message reports",
"center.reportsDesc":
"Flag button under assistant responses. Off = the flag turns grey with a “Report disabled” tooltip and new reports are rejected.",
"center.usernameChangeTitle": "Username changes",
"center.usernameChangeDesc":
"Lets users rename themselves in Settings → Profile. Off = the field is locked (admins can still rename accounts).",
"settings.usernameDisabled": "Username changes are disabled by the administrator.",
"center.mailTitle": "Key recovery emails",
"center.mailChecking": "Checking…",
"center.mailFrom": "Enabled — sent from {from}",
"center.mailDefault": "Enabled — sent from the configured sender",
"center.mailOff": "Disabled — set SMTP_HOST on the server to enable",
"center.mailNote":
"SMTP credentials live in the server environment (see docs/OPERATIONS.md), never in this UI. Users set their recovery address in profile settings or at account creation.",
"center.on": "On",
"center.off": "Off",
"share.fallback": "Shared chat",
"share.open": "Open KisAssistant",
"share.gone": "This shared chat is gone",
"share.goneSub": "The link is invalid, expired, or the author unshared it.",
"share.back": "Go back",
"share.loading": "Loading shared chat…",
"share.by": "by {name}",
"reset.checking": "Checking link…",
"reset.invalid": "Link invalid",
"reset.invalidSub":
"This reset link is unknown, already used, or expired. Request a new one from the login page.",
"reset.readyTitle": "Reset key for @{user}?",
"reset.readySub":
"This issues a fresh access key immediately. Your old key stops working.",
"reset.issue": "Issue new key",
"reset.issuing": "Issuing…",
"reset.doneTitle": "New key ready",
"reset.doneSub":
"Copy it now — it won't be shown again. Then log in with it.",
"reset.goLogin": "Go to login",
"reset.failed": "Reset failed",
"app.deleteConvTitle": "Delete conversation?",
"app.deleteConvMsg":
"“{title}” and all its messages will be permanently removed.",
"settings.language": "Language",
"settings.languageHint":
"Interface language. Applied instantly, saved on this device.",
"settings.security": "Security",
"sec.accessKey": "Access key",
"sec.accessKeyHint":
"Rotate your access key. Old sessions are revoked immediately — you'll log back in with the new key.",
"sec.rotate": "Rotate my access key",
"sec.rotateConfirm": "Click again to confirm rotation",
"sec.rotationFailed": "Rotation failed",
"sec.totp": "Two-factor (TOTP)",
"sec.totpChecking": "Checking…",
"sec.totpAddHint":
"Add a 6-digit code from your authenticator app on top of your access key.",
"sec.totpEnable": "Enable two-factor",
"sec.totpSecretHint":
"Add this secret to your authenticator app (or open the otpauth link), then enter a code to confirm:",
"sec.totpConfirm": "Confirm",
"sec.totpDisableLabel": "Disable with a current code",
"sec.totpDisable": "Disable 2FA",
"sec.setupFailed": "Setup failed",
"sec.passkeys": "Passkeys",
"sec.passkeysHint":
"WebAuthn / platform authenticators — needs a server RP setup.",
"sec.danger": "Danger zone",
"sec.dangerHint":
"Permanently delete your account with all chats, shares and sessions. Cannot be undone.",
"sec.deleteMe": "Delete my account",
"sec.deleteFailed": "Delete failed",
"sec.newKeyTitle": "New access key",
"sec.newKeyHint":
"Copy it now — it won't be shown again. Your old sessions are revoked.",
"sec.newKeyDone": "Done — log me out",
"sec.deleteTitle": "Delete your account?",
"sec.deleteMsg":
"This permanently removes your account with all conversations, shares and sessions. This cannot be undone.",
"sec.deleteForever": "Delete forever",
"sec.avatarTooBig": "File too large (max 5MB).",
"sec.avatarType": "Only jpg, png or webp images are accepted.",
"center.tabAccess": "Access",
"center.smtpHost": "Host",
"center.smtpPort": "Port",
"center.smtpUser": "User",
"center.smtpPass": "Password",
"center.smtpFrom": "From",
"center.smtpAppUrl": "App URL",
"center.notSet": "(not set)",
"center.noAuth": "(no auth)",
"center.tlsImplicit": "implicit TLS (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Show SMTP password",
"center.hidePass": "Hide SMTP password",
"center.hiddenPass": "hidden password",
"center.mailTestTitle": "Connectivity test",
"center.mailTestDesc":
"Verify the connection, then send a real test mail to an address you control.",
"center.verifyConn": "Verify connection",
"center.verifying": "Verifying…",
"center.sendTest": "Send test mail",
"center.sendingMail": "Sending…",
"center.testToAria": "Test recipient email",
"center.connOk": "Connection OK — SMTP host reachable, auth accepted.",
"center.verifyFailed": "Verification failed",
"center.testSent": "Test mail sent to {to}{tail}.",
"center.mailSendFailed": "Send failed",
"center.credsNote":
"Credentials live in the server environment (see docs/OPERATIONS.md), read-only here. Users set their recovery address in profile settings or at account creation.",
"access.status.pending": "Pending",
"access.status.reviewing": "Reviewing",
"access.status.accepted": "Accepted",
"access.status.refused": "Refused",
"access.filter.all": "all",
"access.filter.pending": "pending",
"access.filter.reviewing": "reviewing",
"access.filter.accepted": "accepted",
"access.filter.refused": "refused",
"access.refresh": "Refresh",
"access.refreshAria": "Refresh requests",
"access.empty": "No access requests. The wishlist is empty.",
"access.emptyFiltered": "Nothing with this status.",
"access.msgOne": "1 message",
"access.msgMany": "{n} messages",
"access.accountCreated": "Account created — key shown once, copy it now:",
"access.replyPh": "Reply (emailed to the requester)…",
"access.replyAria": "Reply to requester",
"access.reasonLabel": "Reason (emailed with the decision)",
"access.reasonPh": "Optional reason…",
"access.btnReviewing": "Reviewing",
"access.btnAccept": "Accept",
"access.btnRefuse": "Refuse",
"access.closedNote": "Ticket closed ({status}).",
"access.reasonWord": "Reason",
"access.youAdmin": "You (admin)",
"access.sendFailed": "Send failed",
"access.updateFailed": "Update failed",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Copy message",
"msg.search": "Search the web",
"msg.report": "Report response",
"msg.reportDisabled": "Report disabled",
"msg.retry": "Retry",
"report.title": "Report this response",
"report.reason": "Reason",
"report.reasonPh": "Select a reason…",
"report.reason.copyright": "Copyright",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "False information",
"report.reason.bug": "Bug",
"report.details": "Details (optional)",
"report.detailsPh": "What is wrong with this response? (optional)",
"report.submit": "Send report",
"report.sent": "Report sent — an admin will review it.",
"report.failed": "Could not send the report",
"center.tabReports": "Reports",
"reports.filter.all": "all",
"reports.filter.open": "open",
"reports.filter.reviewing": "reviewing",
"reports.filter.resolved": "resolved",
"reports.filter.dismissed": "dismissed",
"reports.status.open": "Open",
"reports.status.reviewing": "Reviewing",
"reports.status.resolved": "Resolved",
"reports.status.dismissed": "Dismissed",
"reports.refresh": "Refresh",
"reports.refreshAria": "Refresh reports",
"reports.empty": "No content reports yet.",
"reports.emptyFiltered": "Nothing with this status.",
"reports.response": "Reported response",
"reports.noContent": "No content captured.",
"reports.model": "Model",
"reports.reporter": "Reporter",
"reports.conversation": "Conversation",
"reports.detailsGiven": "Reporter details",
"reports.noteLabel": "Admin note",
"reports.notePh": "Internal note…",
"reports.noteWord": "Note",
"reports.btnReviewing": "Reviewing",
"reports.btnResolve": "Resolve",
"reports.btnDismiss": "Dismiss",
"reports.updateFailed": "Update failed",
"reports.closedNote": "Report {status}.",
"report.alreadyReported": "This response was already reported.",
"reports.prompt": "User prompt",
"reports.unreliable": "Unreliable reporter",
"reports.shadowban": "Shadow-ban reporter",
"reports.unshadowban": "Lift shadow-ban",
"reports.shadowbanTitle": "Shadow-ban this reporter?",
"reports.shadowbanMsg": "@{user}'s reports will still be accepted but marked unreliable and hidden from the badge.",
"reports.unshadowbanTitle": "Lift the shadow-ban?",
"reports.unshadowbanMsg": "@{user}'s reports will count toward the badge again.",
"review.title": "Access request",
"review.loadingTicket": "Loading ticket…",
"review.notFound": "Ticket not found",
"review.notFoundSub":
"This link is unknown. Check the URL from your email, or file a new request from the login page.",
"review.adminNote": "Admin note:",
"review.acceptedHint":
"Your account was created — check your email for the access key, then log in.",
"review.closedHint":
"This ticket is closed. Replies by email are not read — if needed, file a new request.",
"review.replyPh": "Argue your case…",
"review.replyAria": "Reply to your ticket",
"review.mailHint":
"Email notifications are one-way — always reply here, not by email.",
"review.status.pending": "Pending review",
"review.status.reviewing": "Under review",
"review.status.accepted": "Accepted",
"review.status.refused": "Refused",
"review.admin": "Admin",
"review.you": "You",
"review.requestTitle": "Request access",
"review.requestIntro":
"Reserve a username and tell us why you want in. An admin reviews every request — you follow the discussion on your personal ticket page and by email.",
"review.emailHint":
"Required — status updates and ticket replies land here.",
"review.whyLabel": "Why should you get access?",
"review.whyHint": "10+ characters. This starts your ticket thread.",
"review.whyPh": "I want to…",
"review.emailLabel": "Email",
"review.sendRequest": "Send request",
"review.received": "Request received",
"review.reserved":
"@{user} is reserved for you while an admin reviews it. A confirmation email with your personal ticket link is on its way.",
"review.copyLink": "Copy link",
"review.openTicket": "Open my ticket",
"admin.editUserTitle": "Edit @{user}",
"admin.avatarUrl": "Avatar URL",
"archived.readonly": "This chat is archived and read-only.",
"archived.unarchive": "Unarchive",
"archived.title": "Archived chats",
"archived.empty": "No archived conversations yet.",
"archived.view": "View",
"archived.deleteTitle": "Delete this archived chat?",
"archived.deleteMsg": "This permanently removes the conversation and all its messages.",
} as const;
export type StringKey = keyof typeof en;
type Dict = Record<StringKey, string>;
const es: Dict = {
"common.close": "Cerrar",
"common.cancel": "Cancelar",
"common.save": "Guardar",
"common.done": "Listo",
"common.copy": "Copiar",
"common.copied": "Copiado",
"common.create": "Crear",
"common.delete": "Eliminar",
"common.loading": "Cargando…",
"common.saving": "Guardando…",
"common.username": "Nombre de usuario",
"common.displayName": "Nombre visible",
"common.select": "Elegir…",
"common.theme": "Tema",
"common.themeAuto": "Automático",
"common.themeAutoFull": "Automático (según el sistema)",
"common.themeSunset": "Puesta de sol",
"common.themeSunsetFull": "Puesta de sol (hora local)",
"common.light": "Claro",
"common.dark": "Oscuro",
"common.saveFailed": "No se pudo guardar",
"common.loadFailed": "No se pudo cargar",
"common.deleteFailed": "No se pudo eliminar",
"common.backToLogin": "Volver al inicio de sesión",
"loading.tagline": "Preparando tus chats",
"login.welcome": "Bienvenido de nuevo",
"login.subtitle": "Inicia sesión en KisAssistant para continuar",
"login.usernamePh": "Nombre de usuario",
"login.keyPh": "Clave de acceso",
"login.failed": "Error de inicio de sesión",
"login.unlock": "Desbloquear",
"login.newHere": "¿Nuevo por aquí?",
"login.register": "Registrarse",
"login.regTipOn": "Crear una cuenta",
"login.regTipOff": "El registro está desactivado en esta plataforma",
"login.requestAccess": "Solicitar acceso",
"login.forgot": "¿Olvidaste tu clave de acceso?",
"login.perk1": "Privado por diseño — sin cookies ni rastreo",
"login.perk2": "Tus propios modelos, en tiempo real",
"login.adminNotePre": "La clave de admin vive en el .env del servidor",
"login.adminNotePost": "; las claves de usuario las emite el admin.",
"login.totpIntro": "Doble factor para @{user} — escribe el código de 6 dígitos de tu app.",
"login.totpAria": "Código de autenticación",
"login.totpInvalid": "Código inválido",
"login.verify": "Verificar",
"sidebar.newChat": "Nuevo chat",
"sidebar.collapse": "Ocultar barra lateral",
"sidebar.closeDrawer": "Cerrar chats",
"sidebar.searchPh": "Buscar chats…",
"sidebar.searchAria": "Buscar conversaciones",
"sidebar.clearSearch": "Borrar búsqueda",
"sidebar.searching": "Buscando…",
"sidebar.noMatch": "Sin resultados para «{q}».",
"sidebar.youPrefix": "tú: ",
"sidebar.emptyA": "Aún no hay conversaciones.",
"sidebar.emptyB": "Empieza un nuevo chat arriba.",
"sidebar.rename": "Renombrar",
"sidebar.topic": "Definir tema",
"sidebar.share": "Compartir públicamente",
"sidebar.delete": "Eliminar",
"sidebar.convOptions": "Opciones de conversación",
"sidebar.admin": "admin",
"sidebar.adminCenter": "Centro de admin",
"sidebar.adminCenterTip": "Abrir el Centro de admin",
"sidebar.settingsTip": "Perfil y ajustes",
"sidebar.logout": "Cerrar sesión",
"sidebar.archive": "Archivar",
"chat.expand": "Mostrar barra lateral",
"chat.openNav": "Abrir chats",
"chat.modelAria": "Modelo",
"chat.noModels": "Sin modelos",
"chat.selectModel": "Elegir modelo…",
"chat.personalTag": "clave personal",
"toast.chatDeleted": "Chat “{title}” eliminado",
"toast.chatArchived": "Chat “{title}” archivado",
"toast.chatUnarchived": "Chat “{title}” desarchivado",
"toast.modelChanged": "Modelo: {label}",
"toast.themeChanged": "Tema cambiado",
"toast.accentChanged": "Color de acento cambiado",
"toast.unshared": "Enlace compartido eliminado",
"toast.settingsSaved": "Ajustes guardados",
"toast.convUpdated": "Conversación “{title}” actualizada",
"chat.you": "Tú",
"chat.greet": "¿En qué te ayudo, {name}?",
"chat.greetSub": "Elige un modelo y escribe abajo. Markdown soportado.",
"chat.thinking": "Pensando…",
"chat.placeholder": "Escribe a KisAssistant…",
"chat.send": "Enviar",
"chat.attachTip": "Adjuntar un archivo",
"chat.removeAttach": "Quitar {name}",
"chat.ocrOpt": "Transcribir imagen",
"chat.unavailable": "(no disponible)",
"chat.ocrHint": "JPG, PNG, WEBP — OCR en el servidor, revisas el texto antes",
"chat.textOpt": "Adjuntar archivo de texto",
"chat.textHint": "TXT o Markdown, máx. 500KB",
"chat.attachNote":
"Las subidas usan solo herramientas de la plataforma. Las imágenes llegan al modelo como texto revisado — nunca como imágenes.",
"chat.wiki": "Wiki y docs",
"attach.tooBigImg": "Imagen muy grande (máx. 5MB).",
"attach.tooBigText": "Archivo muy grande (máx. 500KB).",
"attach.uploadFailed": "Error al subir",
"attach.kindOcr": "transcripción de imagen",
"attach.kindText": "archivo de texto",
"attach.tpl": "[adjunto {kind}: {name}]",
"attach.chatError": "**Error:** el modelo no respondió. Inténtalo de nuevo.",
"dlg.editConv": "Editar conversación",
"dlg.fTitle": "Título",
"dlg.fTopic": "Tema",
"dlg.topicHint": "Etiqueta corta, p. ej. cocina, rust, viajes.",
"dlg.noTopic": "Sin tema",
"dlg.recoverTitle": "Recuperar clave de acceso",
"dlg.recoverIntro":
"Escribe tu usuario. Recibirás un enlace que emite una clave nueva (la anterior deja de funcionar).",
"dlg.sendLink": "Enviar enlace",
"dlg.reqFailed": "Solicitud fallida",
"dlg.recoverSent":
"Si @{user} existe y tiene email de recuperación, un enlace va en camino{fromPart} (válido 60 minutos, un solo uso).",
"dlg.recoverSentFrom": " desde {from}",
"dlg.spamNote": "Revisa tu bandeja — y el spam, puede haber caído allí.",
"dlg.noMailNote":
"¿No llega nada? Entonces no hay email de recuperación en tu cuenta y no es posible — contacta al administrador del sitio.",
"dlg.registerTitle": "Crear una cuenta",
"dlg.regWelcome":
"¡Bienvenido, @{user}! Tu clave de acceso — cópiala ahora, no se mostrará de nuevo.",
"dlg.regContinue": "Copiar e ir al login",
"dlg.regFailed": "Registro fallido",
"dlg.emailOpt": "Email (opcional, para recuperar la clave)",
"dlg.shareTitle": "Compartir públicamente",
"dlg.shareCreating": "Creando enlace público…",
"dlg.shareIntro": "Cualquiera con este enlace puede leer {title}. Sin login.",
"dlg.unshare": "Dejar de compartir",
"dlg.reviewOcr": "Revisar transcripción",
"dlg.reviewText": "Revisar adjunto de texto",
"dlg.transcribing": "Transcribiendo la imagen en el servidor (OCR)…",
"dlg.uploadingTools": "Subiendo con herramientas de la plataforma…",
"dlg.ocrExpl":
"La imagen se transcribió a texto en el servidor — el modelo recibe este texto, nunca la imagen. Corrige errores abajo y adjunta.",
"dlg.textExpl":
"El archivo se subió con herramientas de la plataforma. Su texto se adjunta a tu mensaje. Edita si quieres y adjunta.",
"dlg.truncWarn":
"Transcripción recortada al límite del servidor — falta el final.",
"dlg.attachBtn": "Adjuntar al mensaje",
"dlg.chars": "{n} caracteres",
"settings.title": "Ajustes",
"settings.searchPh": "Buscar ajustes…",
"settings.searchAria": "Buscar ajustes",
"settings.clearSearch": "Borrar búsqueda",
"settings.noMatch": "Sin ajustes para «{q}».",
"settings.profile": "Perfil",
"settings.appearance": "Apariencia",
"settings.features": "Funciones",
"settings.avatarUpload": "Subir avatar",
"settings.dropIdle": "Suelta una imagen o haz clic para subir",
"settings.dropActive": "¡Suéltala!",
"settings.uploading": "Subiendo…",
"settings.avatarHint": "jpg · png · webp — máx. 5MB — 5 cambios por 2h",
"settings.username": "Nombre de usuario",
"settings.usernameHint":
"Nombre de acceso. 2–32 caracteres: minúsculas, dígitos, . _ -. Efecto inmediato.",
"settings.email": "Email de recuperación",
"settings.emailHint":
"Opcional. Solo para enviarte una clave nueva si la pierdes.",
"settings.accent": "Color de acento",
"settings.accentHint":
"Se aplica al instante, se guarda en este dispositivo.",
"settings.customColor": "Color personalizado",
"settings.customAria": "Color de acento personalizado",
"settings.accentAria": "Acento: {label}",
"settings.featHint":
"Activa funciones del editor. Al instante, en este dispositivo.",
"settings.providers": "Proveedores",
"providers.intro":
"Conecta tus propias claves API. Los modelos de los proveedores conectados aparecen en el menú de modelos de arriba.",
"providers.hint":
"Las claves quedan en este servidor y no se muestran de nuevo — solo los últimos 4 caracteres. El uso se factura a tu propia cuenta y la política de modelos del admin sigue vigente.",
"providers.connected": "Conectado",
"providers.notConnected": "Sin conectar",
"providers.keyPh": "Pega la clave API…",
"providers.saveKey": "Guardar clave",
"providers.removeKey": "Quitar",
"providers.replaceKey": "Reemplazar",
"providers.getKey": "Obtener clave",
"providers.keySaved": "Clave guardada — sus modelos ya están en el menú.",
"providers.keyRemoved": "Clave eliminada.",
"providers.invalidKey": "Esa clave no parece válida (8–256 caracteres, sin espacios).",
"providers.loadFailed": "No se pudieron cargar los proveedores.",
"accent.preset.emerald": "Esmeralda",
"accent.preset.rose": "Rosa",
"accent.preset.blue": "Azul",
"accent.preset.violet": "Violeta",
"accent.preset.amber": "Amarillo",
"accent.preset.orange": "Naranja",
"accent.preset.teal": "Turquesa",
"accent.preset.pink": "Rosa fuerte",
"feat.thinking.label": "Razonamiento",
"feat.thinking.hint":
"Pide al modelo razonar paso a paso antes de responder.",
"feat.attachments.label": "Adjuntos",
"feat.attachments.hint":
"Adjunta imágenes (transcripción OCR) y archivos de texto.",
"feat.deepSearch.label": "Búsqueda profunda",
"feat.deepSearch.hint":
"Deja al asistente buscar fuentes frescas. Próximamente.",
"feat.soon": "(pronto)",
"admin.title": "Cuentas",
"admin.intro":
"Cuentas sin KYC: creas un usuario, entregas la clave una vez. Se guardan con hash — regenera para rotar.",
"admin.keyOnce": "Clave para @{user} — se muestra una vez, cópiala ahora:",
"admin.newAccount": "Nueva cuenta",
"admin.email": "Email (recuperación)",
"admin.createFailed": "No se pudo crear",
"admin.regenFailed": "No se pudo regenerar",
"admin.deleteFailed": "No se pudo eliminar",
"admin.loadFailed": "No se pudo cargar",
"admin.searchPh": "Buscar cuentas…",
"admin.searchAria": "Buscar cuentas",
"admin.sortAria": "Ordenar cuentas",
"admin.filterAria": "Filtrar cuentas",
"admin.sortNewest": "Más nuevas",
"admin.sortOldest": "Más viejas",
"admin.sortAz": "A → Z",
"admin.sortZa": "Z → A",
"admin.filterAll": "Todas las cuentas",
"admin.filterWith": "Con email de recuperación",
"admin.filterNo": "Sin email de recuperación",
"admin.countMany": "{total} cuentas · página {page} de {pages}",
"admin.countOne": "{total} cuenta · página {page} de {pages}",
"admin.noEmail": "sin email de recuperación",
"admin.editProfile": "Editar perfil",
"admin.regenKey": "Regenerar clave (revoca sesiones)",
"admin.deleteAccount": "Eliminar cuenta",
"admin.deleteTitle": "¿Eliminar @{user}?",
"admin.deleteMsg": "Esto elimina la cuenta, sus conversaciones y sus shares.",
"admin.prevPage": "Página anterior",
"admin.nextPage": "Página siguiente",
"ollama.models": "Modelos Ollama",
"ollama.desc":
"Descarga modelos de la librería Ollama a tu host, o elimina los locales. Solo admin.",
"ollama.pulling": "Descargando {name}",
"ollama.customTag": "Etiqueta personalizada",
"ollama.customHint": "p. ej. llama3.2:3b, o un nombre de librería",
"ollama.pull": "Descargar",
"ollama.installed": "Instalados ({n})",
"ollama.noneYet": "Aún no hay modelos Ollama locales.",
"ollama.catalog": "Catálogo",
"ollama.delTitle": "¿Eliminar {name}?",
"ollama.delMsg":
"El modelo se elimina del host Ollama. Descárgalo de nuevo cuando quieras.",
"ollama.contacting": "Contactando Ollama…",
"ollama.pullingSt": "Descargando…",
"ollama.doneSt": "Listo",
"ollama.pullFailed": "Descarga fallida",
"ollama.delTip": "Eliminar {name}",
"ollama.sizeAria": "tamaño de {name}",
"ollama.cat.llama3_2": "Modelo compacto de Meta para el día a día",
"ollama.cat.llama3_1": "El caballo de batalla de Meta",
"ollama.cat.qwen2_5": "Multilingüe versátil de Alibaba",
"ollama.cat.gemma2": "Modelo abierto y eficiente de Google",
"ollama.cat.mistral": "Mistral 7B — rápido y capaz",
"ollama.cat.phi3": "Modelo pequeño de investigación de Microsoft",
"ollama.cat.deepseek_r1": "Modelo de razonamiento (cadena de pensamiento)",
"ollama.cat.codellama": "Autocompletado y chat de código",
"ollama.cat.llava": "Modelo de visión (entiende imágenes)",
"ollama.cat.nomic_embed_text": "Embeddings de texto",
"center.title": "Centro de admin",
"center.back": "Volver al chat",
"center.tabAccounts": "Cuentas",
"center.tabFeatures": "Funciones",
"center.tabMail": "Correo",
"center.tabModels": "Modelos",
"models.title": "Modelos",
"models.desc": "Activa o limita cada modelo. Los modelos desactivados desaparecen del selector; los límites se aplican por usuario (los admins no tienen límite).",
"models.refresh": "Actualizar",
"models.refreshAria": "Actualizar modelos",
"models.enabled": "Activado",
"models.hourly": "por hora",
"models.daily": "por día",
"models.unlimited": "Ilimitado",
"models.ollamaTitle": "Biblioteca Ollama",
"models.ollamaDesc": "Descargar o eliminar modelos locales.",
"models.empty": "No hay modelos disponibles.",
"models.saveFailed": "No se pudo guardar",
"models.connTitle": "Conectividad Ollama",
"models.connDesc": "Estado en vivo del servidor Ollama: alcance, versión, latencia y modelos instalados.",
"models.connOnline": "En línea",
"models.connOffline": "Sin conexión",
"models.connDisabledState": "Desactivado",
"models.connCheck": "Comprobar ahora",
"models.connCheckAria": "Comprobar la conectividad Ollama ahora",
"models.connHost": "Host",
"models.connVersion": "Versión",
"models.connLatency": "Latencia",
"models.connModels": "Modelos",
"models.connEmpty": "Aún no hay modelos en el servidor Ollama — descarga uno desde la biblioteca.",
"models.connHint": "Asegúrate de que Ollama esté en marcha y de que OLLAMA_HOST apunte a él.",
"center.locked": "Solo admins",
"center.lockedSub": "Inicia sesión como admin para abrir el Centro de admin.",
"center.regTitle": "Registro público",
"center.regDesc":
"Muestra el botón Registrarse en el login. Off = solo cuentas del admin. Activarlo jubila la lista de espera.",
"center.accTitle": "Solicitudes de acceso (lista)",
"center.accDescOn": "No disponible con registro público — lo reemplaza.",
"center.accDescOff":
"Muestra Solicitar acceso en el login. Triaje en la pestaña Acceso.",
"center.ocrTitle": "Herramienta OCR",
"center.ocrDesc":
"Transcripción de imágenes en el servidor. Requiere tesseract.",
"center.reportsTitle": "Denuncias de mensajes",
"center.reportsDesc":
"Botón de bandera bajo las respuestas. Off = bandera gris con aviso y se rechazan nuevas denuncias.",
"center.usernameChangeTitle": "Cambios de nombre",
"center.usernameChangeDesc":
"Permite renombrarse en Ajustes → Perfil. Off = campo bloqueado (el admin aún puede renombrar).",
"settings.usernameDisabled": "El administrador ha desactivado los cambios de nombre.",
"center.mailTitle": "Emails de recuperación",
"center.mailChecking": "Verificando…",
"center.mailFrom": "Activado — enviados desde {from}",
"center.mailDefault": "Activado — enviados desde el remitente configurado",
"center.mailOff": "Desactivado — configura SMTP_HOST en el servidor",
"center.mailNote":
"Las credenciales SMTP viven en el servidor (ver docs/OPERATIONS.md), nunca aquí. El email se define en el perfil o al crear la cuenta.",
"center.on": "Sí",
"center.off": "No",
"share.fallback": "Chat compartido",
"share.open": "Abrir KisAssistant",
"share.gone": "Este chat compartido ya no existe",
"share.goneSub": "El enlace no vale, expiró o el autor lo retiró.",
"share.back": "Volver",
"share.loading": "Cargando chat compartido…",
"share.by": "por {name}",
"reset.checking": "Verificando enlace…",
"reset.invalid": "Enlace inválido",
"reset.invalidSub":
"Este enlace no existe, ya se usó o expiró. Pide uno nuevo en el login.",
"reset.readyTitle": "¿Nueva clave para @{user}?",
"reset.readySub":
"Emite una clave nueva al instante. La anterior deja de funcionar.",
"reset.issue": "Emitir nueva clave",
"reset.issuing": "Emitiendo…",
"reset.doneTitle": "Nueva clave lista",
"reset.doneSub":
"Cópiala ahora — no se mostrará de nuevo. Inicia sesión con ella.",
"reset.goLogin": "Ir al login",
"reset.failed": "Recuperación fallida",
"app.deleteConvTitle": "¿Eliminar conversación?",
"app.deleteConvMsg": "«{title}» y sus mensajes se eliminarán.",
"settings.language": "Idioma",
"settings.languageHint":
"Idioma de la interfaz. Al instante, en este dispositivo.",
"settings.security": "Seguridad",
"sec.accessKey": "Clave de acceso",
"sec.accessKeyHint":
"Rota tu clave de acceso. Las sesiones antiguas se revocan al instante — volverás con la nueva.",
"sec.rotate": "Rotar mi clave",
"sec.rotateConfirm": "Pulsa de nuevo para confirmar",
"sec.rotationFailed": "No se pudo rotar",
"sec.totp": "Doble factor (TOTP)",
"sec.totpChecking": "Verificando…",
"sec.totpAddHint":
"Añade un código de 6 dígitos de tu app además de tu clave.",
"sec.totpEnable": "Activar doble factor",
"sec.totpSecretHint":
"Añade este secreto a tu app (o abre el enlace otpauth) y escribe un código para confirmar:",
"sec.totpConfirm": "Confirmar",
"sec.totpDisableLabel": "Desactivar con un código actual",
"sec.totpDisable": "Desactivar 2FA",
"sec.setupFailed": "No se pudo configurar",
"sec.passkeys": "Passkeys",
"sec.passkeysHint":
"WebAuthn / autenticadores del sistema — requiere RP en el servidor.",
"sec.danger": "Zona de peligro",
"sec.dangerHint":
"Elimina tu cuenta con chats, shares y sesiones. Sin vuelta atrás.",
"sec.deleteMe": "Eliminar mi cuenta",
"sec.deleteFailed": "No se pudo eliminar",
"sec.newKeyTitle": "Nueva clave de acceso",
"sec.newKeyHint":
"Cópiala ahora — no se mostrará de nuevo. Tus sesiones se revocan.",
"sec.newKeyDone": "Listo — cerrar sesión",
"sec.deleteTitle": "¿Eliminar tu cuenta?",
"sec.deleteMsg":
"Esto elimina tu cuenta con conversaciones, shares y sesiones. Sin vuelta atrás.",
"sec.deleteForever": "Eliminar para siempre",
"sec.avatarTooBig": "Archivo muy grande (máx. 5MB).",
"sec.avatarType": "Solo se aceptan imágenes jpg, png o webp.",
"center.tabAccess": "Acceso",
"center.smtpHost": "Servidor",
"center.smtpPort": "Puerto",
"center.smtpUser": "Usuario",
"center.smtpPass": "Contraseña",
"center.smtpFrom": "Remitente",
"center.smtpAppUrl": "URL de la app",
"center.notSet": "(sin definir)",
"center.noAuth": "(sin auth)",
"center.tlsImplicit": "TLS implícito (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Mostrar contraseña SMTP",
"center.hidePass": "Ocultar contraseña SMTP",
"center.hiddenPass": "contraseña oculta",
"center.mailTestTitle": "Prueba de conexión",
"center.mailTestDesc":
"Verifica la conexión y envía un email real a una dirección tuya.",
"center.verifyConn": "Verificar conexión",
"center.verifying": "Verificando…",
"center.sendTest": "Enviar email de prueba",
"center.sendingMail": "Enviando…",
"center.testToAria": "Email de prueba",
"center.connOk": "Conexión OK — SMTP accesible, auth aceptada.",
"center.verifyFailed": "Verificación fallida",
"center.testSent": "Email enviado a {to}{tail}.",
"center.mailSendFailed": "No se pudo enviar",
"center.credsNote":
"Las credenciales viven en el servidor (ver docs/OPERATIONS.md), solo lectura aquí. El email se define en el perfil o al crear la cuenta.",
"access.status.pending": "Pendiente",
"access.status.reviewing": "En revisión",
"access.status.accepted": "Aceptada",
"access.status.refused": "Rechazada",
"access.filter.all": "todas",
"access.filter.pending": "pendientes",
"access.filter.reviewing": "en revisión",
"access.filter.accepted": "aceptadas",
"access.filter.refused": "rechazadas",
"access.refresh": "Actualizar",
"access.refreshAria": "Actualizar solicitudes",
"access.empty": "Sin solicitudes. La lista está vacía.",
"access.emptyFiltered": "Nada con este estado.",
"access.msgOne": "1 mensaje",
"access.msgMany": "{n} mensajes",
"access.accountCreated": "Cuenta creada — clave única, cópiala ahora:",
"access.replyPh": "Responder (llega por email)…",
"access.replyAria": "Responder al solicitante",
"access.reasonLabel": "Motivo (se envía con la decisión)",
"access.reasonPh": "Motivo opcional…",
"access.btnReviewing": "Revisar",
"access.btnAccept": "Aceptar",
"access.btnRefuse": "Rechazar",
"access.closedNote": "Ticket cerrado ({status}).",
"access.reasonWord": "Motivo",
"access.youAdmin": "Tú (admin)",
"access.sendFailed": "No se pudo enviar",
"access.updateFailed": "No se pudo actualizar",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Copiar mensaje",
"msg.search": "Buscar en la web",
"msg.report": "Denunciar respuesta",
"msg.reportDisabled": "Denuncias desactivadas",
"msg.retry": "Reintentar",
"report.title": "Denunciar esta respuesta",
"report.reason": "Motivo",
"report.reasonPh": "Selecciona un motivo…",
"report.reason.copyright": "Derechos de autor",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "Información falsa",
"report.reason.bug": "Error",
"report.details": "Detalles (opcional)",
"report.detailsPh": "¿Qué tiene de malo esta respuesta? (opcional)",
"report.submit": "Enviar denuncia",
"report.sent": "Denuncia enviada — un administrador la revisará.",
"report.failed": "No se pudo enviar la denuncia",
"center.tabReports": "Denuncias",
"reports.filter.all": "todas",
"reports.filter.open": "abiertas",
"reports.filter.reviewing": "en revisión",
"reports.filter.resolved": "resueltas",
"reports.filter.dismissed": "descartadas",
"reports.status.open": "Abierta",
"reports.status.reviewing": "En revisión",
"reports.status.resolved": "Resuelta",
"reports.status.dismissed": "Descartada",
"reports.refresh": "Actualizar",
"reports.refreshAria": "Actualizar denuncias",
"reports.empty": "Aún no hay denuncias de contenido.",
"reports.emptyFiltered": "Nada con este estado.",
"reports.response": "Respuesta denunciada",
"reports.noContent": "Sin contenido capturado.",
"reports.model": "Modelo",
"reports.reporter": "Denunciante",
"reports.conversation": "Conversación",
"reports.detailsGiven": "Detalles del denunciante",
"reports.noteLabel": "Nota del administrador",
"reports.notePh": "Nota interna…",
"reports.noteWord": "Nota",
"reports.btnReviewing": "En revisión",
"reports.btnResolve": "Resolver",
"reports.btnDismiss": "Descartar",
"reports.updateFailed": "No se pudo actualizar",
"reports.closedNote": "Denuncia {status}.",
"report.alreadyReported": "Esta respuesta ya fue denunciada.",
"reports.prompt": "Pregunta del usuario",
"reports.unreliable": "Denunciante no fiable",
"reports.shadowban": "Silenciar denunciante",
"reports.unshadowban": "Quitar silencio",
"reports.shadowbanTitle": "¿Silenciar a este denunciante?",
"reports.shadowbanMsg": "Las denuncias de @{user} se seguirán aceptando, pero se marcarán como no fiables y no contarán en el contador.",
"reports.unshadowbanTitle": "¿Quitar el silencio?",
"reports.unshadowbanMsg": "Las denuncias de @{user} volverán a contar.",
"review.title": "Solicitud de acceso",
"review.loadingTicket": "Cargando ticket…",
"review.notFound": "Ticket no encontrado",
"review.notFoundSub":
"Este enlace no existe. Revisa la URL de tu email o pide acceso desde el login.",
"review.adminNote": "Nota del admin:",
"review.acceptedHint":
"Tu cuenta fue creada — revisa tu email con la clave e inicia sesión.",
"review.closedHint":
"Ticket cerrado. Los emails no se leen — si hace falta, pide acceso de nuevo.",
"review.replyPh": "Defiende tu caso…",
"review.replyAria": "Responder a tu ticket",
"review.mailHint":
"Los emails son unidireccionales — responde aquí, no por email.",
"review.status.pending": "Pendiente de revisión",
"review.status.reviewing": "En revisión",
"review.status.accepted": "Aceptada",
"review.status.refused": "Rechazada",
"review.admin": "Admin",
"review.you": "Tú",
"review.requestTitle": "Solicitar acceso",
"review.requestIntro":
"Reserva un usuario y cuéntanos por qué quieres entrar. Un admin revisa cada solicitud — sigues el hilo en tu ticket y por email.",
"review.emailHint":
"Obligatorio — avisos y respuestas llegan aquí.",
"review.whyLabel": "¿Por qué darte acceso?",
"review.whyHint": "10+ caracteres. Esto abre tu ticket.",
"review.whyPh": "Quiero…",
"review.emailLabel": "Email",
"review.sendRequest": "Enviar solicitud",
"review.received": "Solicitud recibida",
"review.reserved":
"@{user} queda reservado mientras un admin lo revisa. Un email con tu ticket va en camino.",
"review.copyLink": "Copiar enlace",
"review.openTicket": "Abrir mi ticket",
"admin.editUserTitle": "Editar @{user}",
"admin.avatarUrl": "URL del avatar",
"archived.readonly": "Este chat está archivado y es de solo lectura.",
"archived.unarchive": "Desarchivar",
"archived.title": "Chats archivados",
"archived.empty": "No hay conversaciones archivadas.",
"archived.view": "Ver",
"archived.deleteTitle": "¿Eliminar este chat archivado?",
"archived.deleteMsg": "Esto elimina permanentemente la conversación y todos sus mensajes.",
};
const fr: Dict = {
"common.close": "Fermer",
"common.cancel": "Annuler",
"common.save": "Enregistrer",
"common.done": "Terminé",
"common.copy": "Copier",
"common.copied": "Copié",
"common.create": "Créer",
"common.delete": "Supprimer",
"common.loading": "Chargement…",
"common.saving": "Enregistrement…",
"common.username": "Nom d'utilisateur",
"common.displayName": "Nom affiché",
"common.select": "Choisir…",
"common.theme": "Thème",
"common.themeAuto": "Auto",
"common.themeAutoFull": "Auto (suit le système)",
"common.themeSunset": "Coucher de soleil",
"common.themeSunsetFull": "Coucher de soleil (heure locale)",
"common.light": "Clair",
"common.dark": "Sombre",
"common.saveFailed": "Échec de l'enregistrement",
"common.loadFailed": "Chargement impossible",
"common.deleteFailed": "Suppression impossible",
"common.backToLogin": "Retour à la connexion",
"loading.tagline": "Préparation de vos chats",
"login.welcome": "Bon retour",
"login.subtitle": "Connectez-vous à KisAssistant pour continuer",
"login.usernamePh": "Nom d'utilisateur",
"login.keyPh": "Clé d'accès",
"login.failed": "Échec de connexion",
"login.unlock": "Déverrouiller",
"login.newHere": "Nouveau ici ?",
"login.register": "S'inscrire",
"login.regTipOn": "Créer un compte",
"login.regTipOff": "Inscription désactivée sur cette plateforme",
"login.requestAccess": "Demander l'accès",
"login.forgot": "Clé d'accès oubliée ?",
"login.perk1": "Privé par conception — sans cookies ni suivi",
"login.perk2": "Vos propres modèles, en temps réel",
"login.adminNotePre": "La clé admin vit dans le .env du serveur",
"login.adminNotePost": " ; les clés utilisateur sont émises par l'admin.",
"login.totpIntro": "Double facteur pour @{user} — entrez le code à 6 chiffres de votre app.",
"login.totpAria": "Code d'authentification",
"login.totpInvalid": "Code invalide",
"login.verify": "Vérifier",
"sidebar.newChat": "Nouveau chat",
"sidebar.collapse": "Masquer la barre latérale",
"sidebar.closeDrawer": "Fermer les chats",
"sidebar.searchPh": "Rechercher…",
"sidebar.searchAria": "Rechercher des conversations",
"sidebar.clearSearch": "Effacer la recherche",
"sidebar.searching": "Recherche…",
"sidebar.noMatch": "Aucun résultat pour « {q} ».",
"sidebar.youPrefix": "vous : ",
"sidebar.emptyA": "Aucune conversation.",
"sidebar.emptyB": "Démarrez un nouveau chat ci-dessus.",
"sidebar.rename": "Renommer",
"sidebar.topic": "Définir le sujet",
"sidebar.share": "Partager publiquement",
"sidebar.delete": "Supprimer",
"sidebar.convOptions": "Options de conversation",
"sidebar.admin": "admin",
"sidebar.adminCenter": "Centre admin",
"sidebar.adminCenterTip": "Ouvrir le Centre admin",
"sidebar.settingsTip": "Profil et réglages",
"sidebar.logout": "Déconnexion",
"sidebar.archive": "Archiver",
"chat.expand": "Afficher la barre latérale",
"chat.openNav": "Ouvrir les chats",
"chat.modelAria": "Modèle",
"chat.noModels": "Aucun modèle",
"chat.selectModel": "Choisir un modèle…",
"chat.personalTag": "clé personnelle",
"toast.chatDeleted": "Chat “{title}” supprimé",
"toast.chatArchived": "Chat “{title}” archivé",
"toast.chatUnarchived": "Chat “{title}” désarchivé",
"toast.modelChanged": "Modèle : {label}",
"toast.themeChanged": "Thème modifié",
"toast.accentChanged": "Couleur d’accent modifiée",
"toast.unshared": "Lien de partage retiré",
"toast.settingsSaved": "Réglages enregistrés",
"toast.convUpdated": "Conversation “{title}” mise à jour",
"chat.you": "Vous",
"chat.greet": "Comment puis-je aider, {name} ?",
"chat.greetSub":
"Choisissez un modèle, puis écrivez ci-dessous. Markdown pris en charge.",
"chat.thinking": "Réflexion…",
"chat.placeholder": "Écrivez à KisAssistant…",
"chat.send": "Envoyer",
"chat.attachTip": "Joindre un fichier",
"chat.removeAttach": "Retirer {name}",
"chat.ocrOpt": "Transcrire une image",
"chat.unavailable": "(indisponible)",
"chat.ocrHint":
"JPG, PNG, WEBP — OCR sur le serveur, vous relisez le texte avant",
"chat.textOpt": "Joindre un fichier texte",
"chat.textHint": "TXT ou Markdown, 500 Ko max",
"chat.attachNote":
"Les envois passent uniquement par les outils de la plateforme. Les images arrivent au modèle comme texte relu — jamais brutes.",
"chat.wiki": "Wiki et docs",
"attach.tooBigImg": "Image trop lourde (5 Mo max).",
"attach.tooBigText": "Fichier trop lourd (500 Ko max).",
"attach.uploadFailed": "Échec de l'envoi",
"attach.kindOcr": "transcription d'image",
"attach.kindText": "fichier texte",
"attach.tpl": "[pièce jointe {kind} : {name}]",
"attach.chatError": "**Erreur :** le modèle n'a pas répondu. Réessayez.",
"dlg.editConv": "Modifier la conversation",
"dlg.fTitle": "Titre",
"dlg.fTopic": "Sujet",
"dlg.topicHint": "Courte étiquette, p. ex. cuisine, rust, voyages.",
"dlg.noTopic": "Sans sujet",
"dlg.recoverTitle": "Récupérer la clé d'accès",
"dlg.recoverIntro":
"Entrez votre nom d'utilisateur. Vous recevrez un lien qui émet une clé neuve (l'ancienne cesse de fonctionner).",
"dlg.sendLink": "Envoyer le lien",
"dlg.reqFailed": "Requête échouée",
"dlg.recoverSent":
"Si @{user} existe avec un email de récupération, un lien est en route{fromPart} (valide 60 minutes, usage unique).",
"dlg.recoverSentFrom": " depuis {from}",
"dlg.spamNote":
"Vérifiez votre boîte — et les spams, le message a pu y atterrir.",
"dlg.noMailNote":
"Rien ne vient ? Alors aucun email de récupération n'est défini et c'est impossible — contactez l'administrateur du site.",
"dlg.registerTitle": "Créer un compte",
"dlg.regWelcome":
"Bienvenue, @{user} ! Votre clé d'accès — copiez-la vite, elle ne sera plus affichée.",
"dlg.regContinue": "Copier et aller au login",
"dlg.regFailed": "Inscription échouée",
"dlg.emailOpt": "Email (optionnel, pour récupérer la clé)",
"dlg.shareTitle": "Partager publiquement",
"dlg.shareCreating": "Création du lien public…",
"dlg.shareIntro": "Quiconque a ce lien peut lire {title}. Sans connexion.",
"dlg.unshare": "Ne plus partager",
"dlg.reviewOcr": "Relire la transcription",
"dlg.reviewText": "Relire la pièce jointe",
"dlg.transcribing": "Transcription de l'image sur le serveur (OCR)…",
"dlg.uploadingTools": "Envoi via les outils de la plateforme…",
"dlg.ocrExpl":
"L'image a été transcrite en texte sur le serveur — le modèle reçoit ce texte, jamais l'image. Corrigez ci-dessous puis joignez.",
"dlg.textExpl":
"Le fichier a été envoyé via les outils de la plateforme. Son texte est joint à votre message. Modifiez si besoin puis joignez.",
"dlg.truncWarn":
"Transcription tronquée à la limite serveur — la fin manque.",
"dlg.attachBtn": "Joindre au message",
"dlg.chars": "{n} caractères",
"settings.title": "Réglages",
"settings.searchPh": "Rechercher…",
"settings.searchAria": "Rechercher dans les réglages",
"settings.clearSearch": "Effacer la recherche",
"settings.noMatch": "Aucun réglage pour « {q} ».",
"settings.profile": "Profil",
"settings.appearance": "Apparence",
"settings.features": "Fonctions",
"settings.avatarUpload": "Envoyer un avatar",
"settings.dropIdle": "Déposez une image ou cliquez pour envoyer",
"settings.dropActive": "Lâchez !",
"settings.uploading": "Envoi…",
"settings.avatarHint": "jpg · png · webp — 5 Mo max — 5 changements par 2 h",
"settings.username": "Nom d'utilisateur",
"settings.usernameHint":
"Identifiant de connexion. 2–32 car. : minuscules, chiffres, . _ -. Effet immédiat.",
"settings.email": "Email de récupération",
"settings.emailHint": "Optionnel. Sert uniquement à vous renvoyer une clé.",
"settings.accent": "Couleur d'accent",
"settings.accentHint": "Appliquée aussitôt, gardée sur cet appareil.",
"settings.customColor": "Couleur perso",
"settings.customAria": "Couleur d'accent personnalisée",
"settings.accentAria": "Accent : {label}",
"settings.featHint":
"Activez les fonctions du composer. Aussitôt, sur cet appareil.",
"settings.providers": "Fournisseurs",
"providers.intro":
"Connectez vos propres clés API. Les modèles des fournisseurs connectés apparaissent dans le menu des modèles en haut.",
"providers.hint":
"Les clés restent sur ce serveur et ne sont plus jamais affichées — seuls les 4 derniers caractères. L'usage est facturé sur votre propre compte, et la politique de modèles de l'admin reste en vigueur.",
"providers.connected": "Connecté",
"providers.notConnected": "Non connecté",
"providers.keyPh": "Collez la clé API…",
"providers.saveKey": "Enregistrer",
"providers.removeKey": "Retirer",
"providers.replaceKey": "Remplacer",
"providers.getKey": "Obtenir une clé",
"providers.keySaved": "Clé enregistrée — ses modèles sont dans le menu.",
"providers.keyRemoved": "Clé retirée.",
"providers.invalidKey": "Cette clé semble invalide (8–256 caractères, sans espaces).",
"providers.loadFailed": "Impossible de charger les fournisseurs.",
"accent.preset.emerald": "Émeraude",
"accent.preset.rose": "Rose",
"accent.preset.blue": "Bleu",
"accent.preset.violet": "Violet",
"accent.preset.amber": "Jaune",
"accent.preset.orange": "Orange",
"accent.preset.teal": "Sarcelle",
"accent.preset.pink": "Rose vif",
"feat.thinking.label": "Réflexion",
"feat.thinking.hint": "Demande au modèle de raisonner étape par étape.",
"feat.attachments.label": "Pièces jointes",
"feat.attachments.hint":
"Joindre images (transcription OCR) et fichiers texte.",
"feat.deepSearch.label": "Recherche profonde",
"feat.deepSearch.hint":
"Laisse l'assistant chercher des sources fraîches. Bientôt.",
"feat.soon": "(bientôt)",
"admin.title": "Comptes",
"admin.intro":
"Comptes sans KYC : vous créez un pseudo, remettez la clé une fois. Stockées hachées — régénérez pour tourner.",
"admin.keyOnce": "Clé pour @{user} — affichée une fois, copiez-la :",
"admin.newAccount": "Nouveau compte",
"admin.email": "Email (récupération)",
"admin.createFailed": "Création impossible",
"admin.regenFailed": "Régénération impossible",
"admin.deleteFailed": "Suppression impossible",
"admin.loadFailed": "Chargement impossible",
"admin.searchPh": "Rechercher des comptes…",
"admin.searchAria": "Rechercher des comptes",
"admin.sortAria": "Trier les comptes",
"admin.filterAria": "Filtrer les comptes",
"admin.sortNewest": "Plus récents",
"admin.sortOldest": "Plus anciens",
"admin.sortAz": "A → Z",
"admin.sortZa": "Z → A",
"admin.filterAll": "Tous les comptes",
"admin.filterWith": "Avec email de récupération",
"admin.filterNo": "Sans email de récupération",
"admin.countMany": "{total} comptes · page {page} sur {pages}",
"admin.countOne": "{total} compte · page {page} sur {pages}",
"admin.noEmail": "sans email de récupération",
"admin.editProfile": "Modifier le profil",
"admin.regenKey": "Régénérer la clé (révoque les sessions)",
"admin.deleteAccount": "Supprimer le compte",
"admin.deleteTitle": "Supprimer @{user} ?",
"admin.deleteMsg":
"Supprime définitivement le compte, ses conversations et ses partages.",
"admin.prevPage": "Page précédente",
"admin.nextPage": "Page suivante",
"ollama.models": "Modèles Ollama",
"ollama.desc":
"Téléchargez des modèles Ollama sur votre hôte, ou retirez les locaux. Admin uniquement.",
"ollama.pulling": "Téléchargement de {name}",
"ollama.customTag": "Tag personnalisé",
"ollama.customHint": "p. ex. llama3.2:3b, ou un nom de bibliothèque",
"ollama.pull": "Télécharger",
"ollama.installed": "Installés ({n})",
"ollama.noneYet": "Aucun modèle Ollama local.",
"ollama.catalog": "Catalogue",
"ollama.delTitle": "Supprimer {name} ?",
"ollama.delMsg":
"Le modèle est retiré de l'hôte Ollama. Retéléchargez-le à tout moment.",
"ollama.contacting": "Contact d'Ollama…",
"ollama.pullingSt": "Téléchargement…",
"ollama.doneSt": "Terminé",
"ollama.pullFailed": "Échec du téléchargement",
"ollama.delTip": "Supprimer {name}",
"ollama.sizeAria": "taille de {name}",
"ollama.cat.llama3_2": "Le compact de Meta pour tous les jours",
"ollama.cat.llama3_1": "Le bourreau de travail de Meta",
"ollama.cat.qwen2_5": "Polyglotte polyvalent d'Alibaba",
"ollama.cat.gemma2": "Le modèle ouvert et efficace de Google",
"ollama.cat.mistral": "Mistral 7B — rapide et capable",
"ollama.cat.phi3": "Le petit modèle de recherche Microsoft",
"ollama.cat.deepseek_r1": "Modèle de raisonnement (chaîne de pensée)",
"ollama.cat.codellama": "Complétion et chat de code",
"ollama.cat.llava": "Modèle de vision (comprend les images)",
"ollama.cat.nomic_embed_text": "Embeddings de texte",
"center.title": "Centre admin",
"center.back": "Retour au chat",
"center.tabAccounts": "Comptes",
"center.tabFeatures": "Fonctions",
"center.tabMail": "Mail",
"center.tabModels": "Modèles",
"models.title": "Modèles",
"models.desc": "Activez ou limitez chaque modèle. Les modèles désactivés disparaissent du sélecteur ; les limites s'appliquent par utilisateur (les admins ne sont pas limités).",
"models.refresh": "Actualiser",
"models.refreshAria": "Actualiser les modèles",
"models.enabled": "Activé",
"models.hourly": "par heure",
"models.daily": "par jour",
"models.unlimited": "Illimité",
"models.ollamaTitle": "Bibliothèque Ollama",
"models.ollamaDesc": "Télécharger ou supprimer des modèles locaux.",
"models.empty": "Aucun modèle disponible.",
"models.saveFailed": "Enregistrement impossible",
"models.connTitle": "Connectivité Ollama",
"models.connDesc": "État en direct de l'hôte Ollama : joignabilité, version, latence et modèles installés.",
"models.connOnline": "En ligne",
"models.connOffline": "Hors ligne",
"models.connDisabledState": "Désactivé",
"models.connCheck": "Vérifier",
"models.connCheckAria": "Vérifier la connectivité Ollama",
"models.connHost": "Hôte",
"models.connVersion": "Version",
"models.connLatency": "Latence",
"models.connModels": "Modèles",
"models.connEmpty": "Aucun modèle sur l'hôte Ollama — téléchargez-en un depuis la bibliothèque ci-dessous.",
"models.connHint": "Vérifiez qu'Ollama tourne et que OLLAMA_HOST pointe vers lui.",
"center.locked": "Admins uniquement",
"center.lockedSub": "Connectez-vous en admin pour ouvrir le Centre admin.",
"center.regTitle": "Inscription publique",
"center.regDesc":
"Affiche le bouton S'inscrire au login. Off = comptes admin uniquement. L'activer retire la liste d'attente ci-dessous.",
"center.accTitle": "Demandes d'accès (liste)",
"center.accDescOn": "Indispo avec l'inscription publique — elle la remplace.",
"center.accDescOff":
"Affiche Demander l'accès au login. Réservez un pseudo, plaidez votre cas ; tri dans l'onglet Accès.",
"center.ocrTitle": "Outil OCR",
"center.ocrDesc": "Transcription d'images côté serveur. Requiert tesseract.",
"center.reportsTitle": "Signalements de messages",
"center.reportsDesc":
"Bouton drapeau sous les réponses. Off = drapeau grisé avec infobulle et nouveaux signalements refusés.",
"center.usernameChangeTitle": "Changements de pseudo",
"center.usernameChangeDesc":
"Permet de se renommer dans Réglages → Profil. Off = champ verrouillé (l'admin peut toujours renommer).",
"settings.usernameDisabled": "Changements de pseudo désactivés par l'administrateur.",
"center.mailTitle": "Emails de récupération",
"center.mailChecking": "Vérification…",
"center.mailFrom": "Activé — envoyés depuis {from}",
"center.mailDefault": "Activé — envoyés depuis l'expéditeur configuré",
"center.mailOff": "Désactivé — définissez SMTP_HOST sur le serveur",
"center.mailNote":
"Les identifiants SMTP vivent sur le serveur (voir docs/OPERATIONS.md), jamais ici. L'email se règle dans le profil ou à la création.",
"center.on": "Oui",
"center.off": "Non",
"share.fallback": "Chat partagé",
"share.open": "Ouvrir KisAssistant",
"share.gone": "Ce chat partagé n'existe plus",
"share.goneSub": "Le lien est invalide, expiré, ou l'auteur l'a retiré.",
"share.back": "Retour",
"share.loading": "Chargement du chat partagé…",
"share.by": "par {name}",
"reset.checking": "Vérification du lien…",
"reset.invalid": "Lien invalide",
"reset.invalidSub":
"Ce lien est inconnu, déjà utilisé ou expiré. Redemandez-en un au login.",
"reset.readyTitle": "Nouvelle clé pour @{user} ?",
"reset.readySub":
"Émet aussitôt une clé neuve. L'ancienne cesse de fonctionner.",
"reset.issue": "Émettre une clé",
"reset.issuing": "Émission…",
"reset.doneTitle": "Nouvelle clé prête",
"reset.doneSub":
"Copiez-la vite — plus affichée ensuite. Connectez-vous avec.",
"reset.goLogin": "Aller au login",
"reset.failed": "Récupération échouée",
"app.deleteConvTitle": "Supprimer la conversation ?",
"app.deleteConvMsg": "« {title} » et ses messages seront supprimés.",
"settings.language": "Langue",
"settings.languageHint":
"Langue de l'interface. Aussitôt, sur cet appareil.",
"settings.security": "Sécurité",
"sec.accessKey": "Clé d'accès",
"sec.accessKeyHint":
"Faites tourner votre clé. Les anciennes sessions sont révoquées aussitôt — reconnectez-vous avec la neuve.",
"sec.rotate": "Faire tourner ma clé",
"sec.rotateConfirm": "Recliquez pour confirmer",
"sec.rotationFailed": "Rotation impossible",
"sec.totp": "Double facteur (TOTP)",
"sec.totpChecking": "Vérification…",
"sec.totpAddHint":
"Ajoutez un code à 6 chiffres de votre app en plus de votre clé.",
"sec.totpEnable": "Activer le double facteur",
"sec.totpSecretHint":
"Ajoutez ce secret à votre app (ou ouvrez le lien otpauth), puis entrez un code :",
"sec.totpConfirm": "Confirmer",
"sec.totpDisableLabel": "Désactiver avec un code actuel",
"sec.totpDisable": "Désactiver 2FA",
"sec.setupFailed": "Configuration impossible",
"sec.passkeys": "Passkeys",
"sec.passkeysHint":
"WebAuthn / authentificateurs système — requiert un RP serveur.",
"sec.danger": "Zone dangereuse",
"sec.dangerHint":
"Supprime votre compte avec chats, partages et sessions. Irréversible.",
"sec.deleteMe": "Supprimer mon compte",
"sec.deleteFailed": "Suppression impossible",
"sec.newKeyTitle": "Nouvelle clé d'accès",
"sec.newKeyHint":
"Copiez-la vite — plus affichée ensuite. Vos sessions sont révoquées.",
"sec.newKeyDone": "OK — me déconnecter",
"sec.deleteTitle": "Supprimer votre compte ?",
"sec.deleteMsg":
"Supprime définitivement votre compte avec conversations, partages et sessions. Irréversible.",
"sec.deleteForever": "Supprimer pour toujours",
"sec.avatarTooBig": "Fichier trop lourd (5 Mo max).",
"sec.avatarType": "Seules les images jpg, png ou webp sont acceptées.",
"center.tabAccess": "Accès",
"center.smtpHost": "Serveur",
"center.smtpPort": "Port",
"center.smtpUser": "Utilisateur",
"center.smtpPass": "Mot de passe",
"center.smtpFrom": "Expéditeur",
"center.smtpAppUrl": "URL de l'app",
"center.notSet": "(non défini)",
"center.noAuth": "(sans auth)",
"center.tlsImplicit": "TLS implicite (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Afficher le mot de passe SMTP",
"center.hidePass": "Masquer le mot de passe SMTP",
"center.hiddenPass": "mot de passe masqué",
"center.mailTestTitle": "Test de connexion",
"center.mailTestDesc":
"Vérifiez la connexion, puis envoyez un vrai mail de test à une adresse à vous.",
"center.verifyConn": "Vérifier la connexion",
"center.verifying": "Vérification…",
"center.sendTest": "Envoyer un mail de test",
"center.sendingMail": "Envoi…",
"center.testToAria": "Email de test",
"center.connOk": "Connexion OK — hôte SMTP joignable, auth acceptée.",
"center.verifyFailed": "Vérification échouée",
"center.testSent": "Mail de test envoyé à {to}{tail}.",
"center.mailSendFailed": "Envoi impossible",
"center.credsNote":
"Les identifiants vivent sur le serveur (voir docs/OPERATIONS.md), lecture seule ici. L'email se règle dans le profil ou à la création.",
"access.status.pending": "En attente",
"access.status.reviewing": "En examen",
"access.status.accepted": "Acceptée",
"access.status.refused": "Refusée",
"access.filter.all": "tous",
"access.filter.pending": "en attente",
"access.filter.reviewing": "en examen",
"access.filter.accepted": "acceptés",
"access.filter.refused": "refusés",
"access.refresh": "Actualiser",
"access.refreshAria": "Actualiser les demandes",
"access.empty": "Aucune demande. La liste est vide.",
"access.emptyFiltered": "Rien avec ce statut.",
"access.msgOne": "1 message",
"access.msgMany": "{n} messages",
"access.accountCreated": "Compte créé — clé unique, copiez-la :",
"access.replyPh": "Répondre (envoyé par email)…",
"access.replyAria": "Répondre au demandeur",
"access.reasonLabel": "Motif (envoyé avec la décision)",
"access.reasonPh": "Motif optionnel…",
"access.btnReviewing": "Examiner",
"access.btnAccept": "Accepter",
"access.btnRefuse": "Refuser",
"access.closedNote": "Ticket fermé ({status}).",
"access.reasonWord": "Motif",
"access.youAdmin": "Vous (admin)",
"access.sendFailed": "Envoi impossible",
"access.updateFailed": "Mise à jour impossible",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Copier le message",
"msg.search": "Rechercher sur le web",
"msg.report": "Signaler la réponse",
"msg.reportDisabled": "Signalements désactivés",
"msg.retry": "Réessayer",
"report.title": "Signaler cette réponse",
"report.reason": "Motif",
"report.reasonPh": "Choisir un motif…",
"report.reason.copyright": "Droit d'auteur",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "Fausse information",
"report.reason.bug": "Bug",
"report.details": "Détails (facultatif)",
"report.detailsPh": "Qu'est-ce qui ne va pas avec cette réponse ? (facultatif)",
"report.submit": "Envoyer le signalement",
"report.sent": "Signalement envoyé — un admin va l'examiner.",
"report.failed": "Envoi du signalement impossible",
"center.tabReports": "Signalements",
"reports.filter.all": "tous",
"reports.filter.open": "ouverts",
"reports.filter.reviewing": "en cours",
"reports.filter.resolved": "résolus",
"reports.filter.dismissed": "rejetés",
"reports.status.open": "Ouvert",
"reports.status.reviewing": "En cours",
"reports.status.resolved": "Résolu",
"reports.status.dismissed": "Rejeté",
"reports.refresh": "Actualiser",
"reports.refreshAria": "Actualiser les signalements",
"reports.empty": "Aucun signalement pour l'instant.",
"reports.emptyFiltered": "Rien avec ce statut.",
"reports.response": "Réponse signalée",
"reports.noContent": "Aucun contenu capturé.",
"reports.model": "Modèle",
"reports.reporter": "Auteur",
"reports.conversation": "Conversation",
"reports.detailsGiven": "Détails de l'auteur",
"reports.noteLabel": "Note admin",
"reports.notePh": "Note interne…",
"reports.noteWord": "Note",
"reports.btnReviewing": "En cours",
"reports.btnResolve": "Résoudre",
"reports.btnDismiss": "Rejeter",
"reports.updateFailed": "Mise à jour impossible",
"reports.closedNote": "Signalement {status}.",
"report.alreadyReported": "Cette réponse a déjà été signalée.",
"reports.prompt": "Demande de l'utilisateur",
"reports.unreliable": "Signaleur non fiable",
"reports.shadowban": "Shadow-ban le signaleur",
"reports.unshadowban": "Lever le shadow-ban",
"reports.shadowbanTitle": "Shadow-ban ce signaleur ?",
"reports.shadowbanMsg": "Les signalements de @{user} seront toujours acceptés mais marqués non fiables et exclus du compteur.",
"reports.unshadowbanTitle": "Lever le shadow-ban ?",
"reports.unshadowbanMsg": "Les signalements de @{user} compteront à nouveau.",
"review.title": "Demande d'accès",
"review.loadingTicket": "Chargement du ticket…",
"review.notFound": "Ticket introuvable",
"review.notFoundSub":
"Ce lien est inconnu. Vérifiez l'URL de votre email, ou refaites une demande depuis le login.",
"review.adminNote": "Note admin :",
"review.acceptedHint":
"Votre compte est créé — vérifiez votre email avec la clé, puis connectez-vous.",
"review.closedHint":
"Ticket fermé. Les emails ne sont pas lus — si besoin, refaites une demande.",
"review.replyPh": "Plaidez votre cas…",
"review.replyAria": "Répondre à votre ticket",
"review.mailHint":
"Les emails sont à sens unique — répondez ici, pas par email.",
"review.status.pending": "En attente d'examen",
"review.status.reviewing": "En cours d'examen",
"review.status.accepted": "Acceptée",
"review.status.refused": "Refusée",
"review.admin": "Admin",
"review.you": "Vous",
"review.requestTitle": "Demander l'accès",
"review.requestIntro":
"Réservez un pseudo et dites pourquoi vous voulez entrer. Un admin examine chaque demande — suivez le fil sur votre ticket et par email.",
"review.emailHint":
"Requis — avis et réponses arrivent ici.",
"review.whyLabel": "Pourquoi vous donner l'accès ?",
"review.whyHint": "10+ caractères. Ceci ouvre votre ticket.",
"review.whyPh": "Je veux…",
"review.emailLabel": "Email",
"review.sendRequest": "Envoyer la demande",
"review.received": "Demande reçue",
"review.reserved":
"@{user} est réservé pendant l'examen admin. Un email avec votre ticket est en route.",
"review.copyLink": "Copier le lien",
"review.openTicket": "Ouvrir mon ticket",
"admin.editUserTitle": "Modifier @{user}",
"admin.avatarUrl": "URL de l'avatar",
"archived.readonly": "Ce chat est archivé en lecture seule.",
"archived.unarchive": "Désarchiver",
"archived.title": "Conversations archivées",
"archived.empty": "Aucune conversation archivée.",
"archived.view": "Voir",
"archived.deleteTitle": "Supprimer cette conversation archivée ?",
"archived.deleteMsg": "Cela supprime définitivement la conversation et tous ses messages.",
};
const ru: Dict = {
"common.close": "Закрыть",
"common.cancel": "Отмена",
"common.save": "Сохранить",
"common.done": "Готово",
"common.copy": "Копировать",
"common.copied": "Скопировано",
"common.create": "Создать",
"common.delete": "Удалить",
"common.loading": "Загрузка…",
"common.saving": "Сохранение…",
"common.username": "Имя пользователя",
"common.displayName": "Отображаемое имя",
"common.select": "Выбрать…",
"common.theme": "Тема",
"common.themeAuto": "Авто",
"common.themeAutoFull": "Авто (как в системе)",
"common.themeSunset": "Закат",
"common.themeSunsetFull": "Закат (местное время)",
"common.light": "Светлая",
"common.dark": "Тёмная",
"common.saveFailed": "Не удалось сохранить",
"common.loadFailed": "Не загрузилось",
"common.deleteFailed": "Не удалилось",
"common.backToLogin": "Назад ко входу",
"loading.tagline": "Готовим ваши чаты",
"login.welcome": "С возвращением",
"login.subtitle": "Войдите в KisAssistant, чтобы продолжить",
"login.usernamePh": "Имя пользователя",
"login.keyPh": "Ключ доступа",
"login.failed": "Ошибка входа",
"login.unlock": "Разблокировать",
"login.newHere": "Впервые здесь?",
"login.register": "Регистрация",
"login.regTipOn": "Создать аккаунт",
"login.regTipOff": "Регистрация на этой платформе отключена",
"login.requestAccess": "Запросить доступ",
"login.forgot": "Забыли ключ доступа?",
"login.perk1": "Приватность по умолчанию — без cookies и трекинга",
"login.perk2": "Ваши модели, в реальном времени",
"login.adminNotePre": "Ключ админа живёт в .env сервера",
"login.adminNotePost": "; ключи пользователей выдаёт админ.",
"login.totpIntro": "Двухфакторка для @{user} — введите 6-значный код из приложения.",
"login.totpAria": "Код аутентификатора",
"login.totpInvalid": "Неверный код",
"login.verify": "Проверить",
"sidebar.newChat": "Новый чат",
"sidebar.collapse": "Скрыть панель",
"sidebar.closeDrawer": "Закрыть чаты",
"sidebar.searchPh": "Поиск чатов…",
"sidebar.searchAria": "Поиск разговоров",
"sidebar.clearSearch": "Очистить поиск",
"sidebar.searching": "Поиск…",
"sidebar.noMatch": "По запросу «{q}» ничего нет.",
"sidebar.youPrefix": "вы: ",
"sidebar.emptyA": "Пока нет разговоров.",
"sidebar.emptyB": "Начните новый чат выше.",
"sidebar.rename": "Переименовать",
"sidebar.topic": "Задать тему",
"sidebar.share": "Опубликовать ссылку",
"sidebar.delete": "Удалить",
"sidebar.convOptions": "Действия с разговором",
"sidebar.admin": "админ",
"sidebar.adminCenter": "Админ-центр",
"sidebar.adminCenterTip": "Открыть Админ-центр",
"sidebar.settingsTip": "Профиль и настройки",
"sidebar.logout": "Выйти",
"sidebar.archive": "В архив",
"chat.expand": "Показать панель",
"chat.openNav": "Открыть чаты",
"chat.modelAria": "Модель",
"chat.noModels": "Нет моделей",
"chat.selectModel": "Выбрать модель…",
"chat.personalTag": "свой ключ",
"toast.chatDeleted": "Чат “{title}” удалён",
"toast.chatArchived": "Чат “{title}” архивирован",
"toast.chatUnarchived": "Чат “{title}” разархивирован",
"toast.modelChanged": "Модель: {label}",
"toast.themeChanged": "Тема изменена",
"toast.accentChanged": "Акцентный цвет изменён",
"toast.unshared": "Публичная ссылка удалена",
"toast.settingsSaved": "Настройки сохранены",
"toast.convUpdated": "Чат “{title}” обновлён",
"chat.you": "Вы",
"chat.greet": "Чем помочь, {name}?",
"chat.greetSub": "Выберите модель и пишите ниже. Поддерживается Markdown.",
"chat.thinking": "Думаю…",
"chat.placeholder": "Сообщение KisAssistant…",
"chat.send": "Отправить",
"chat.attachTip": "Прикрепить файл",
"chat.removeAttach": "Убрать {name}",
"chat.ocrOpt": "Распознать изображение",
"chat.unavailable": "(недоступно)",
"chat.ocrHint": "JPG, PNG, WEBP — OCR на сервере, текст вы проверите",
"chat.textOpt": "Прикрепить текстовый файл",
"chat.textHint": "TXT или Markdown, до 500 КБ",
"chat.attachNote":
"Загрузка только через инструменты платформы. Изображения уходят модели проверенным текстом — не картинками.",
"chat.wiki": "Вики и доки",
"attach.tooBigImg": "Изображение слишком большое (макс. 5 МБ).",
"attach.tooBigText": "Файл слишком большой (макс. 500 КБ).",
"attach.uploadFailed": "Ошибка загрузки",
"attach.kindOcr": "распознанное изображение",
"attach.kindText": "текстовый файл",
"attach.tpl": "[приложено {kind}: {name}]",
"attach.chatError": "**Ошибка:** модель не ответила. Попробуйте ещё.",
"dlg.editConv": "Изменить разговор",
"dlg.fTitle": "Название",
"dlg.fTopic": "Тема",
"dlg.topicHint": "Короткий тег, напр. кухня, rust, поездки.",
"dlg.noTopic": "Без темы",
"dlg.recoverTitle": "Восстановить ключ",
"dlg.recoverIntro":
"Введите имя пользователя. Вы получите ссылку на новый ключ (старый перестанет работать).",
"dlg.sendLink": "Отправить ссылку",
"dlg.reqFailed": "Запрос не удался",
"dlg.recoverSent":
"Если @{user} существует и у него есть email, ссылка уже летит{fromPart} (действует 60 минут, одноразовая).",
"dlg.recoverSentFrom": " от {from}",
"dlg.spamNote": "Проверьте входящие — и спам, письмо могло попасть туда.",
"dlg.noMailNote":
"Ничего нет? Значит, email не указан и сброс невозможен — обратитесь к администратору сайта.",
"dlg.registerTitle": "Создать аккаунт",
"dlg.regWelcome":
"Добро пожаловать, @{user}! Ваш ключ — скопируйте сейчас, больше не покажем.",
"dlg.regContinue": "Скопировать и ко входу",
"dlg.regFailed": "Ошибка регистрации",
"dlg.emailOpt": "Email (необязательно, для восстановления)",
"dlg.shareTitle": "Опубликовать ссылку",
"dlg.shareCreating": "Создаём публичную ссылку…",
"dlg.shareIntro": "Каждый с этой ссылкой прочитает {title}. Вход не нужен.",
"dlg.unshare": "Закрыть доступ",
"dlg.reviewOcr": "Проверить распознавание",
"dlg.reviewText": "Проверить вложение",
"dlg.transcribing": "Распознаём изображение на сервере (OCR)…",
"dlg.uploadingTools": "Загружаем через инструменты платформы…",
"dlg.ocrExpl":
"Изображение распознано в текст на сервере — модель получит текст, не картинку. Исправьте ошибки ниже и прикрепите.",
"dlg.textExpl":
"Файл загружен через инструменты платформы. Его текст прикрепится к сообщению. Правьте и прикрепляйте.",
"dlg.truncWarn": "Распознавание обрезано лимитом сервера — конца нет.",
"dlg.attachBtn": "Прикрепить к сообщению",
"dlg.chars": "{n} символов",
"settings.title": "Настройки",
"settings.searchPh": "Поиск настроек…",
"settings.searchAria": "Поиск настроек",
"settings.clearSearch": "Очистить поиск",
"settings.noMatch": "Настроек по «{q}» нет.",
"settings.profile": "Профиль",
"settings.appearance": "Внешний вид",
"settings.features": "Функции",
"settings.avatarUpload": "Загрузить аватар",
"settings.dropIdle": "Перетащите картинку или нажмите для загрузки",
"settings.dropActive": "Отпускайте!",
"settings.uploading": "Загрузка…",
"settings.avatarHint": "jpg · png · webp — до 5 МБ — 5 смен за 2 ч",
"settings.username": "Имя пользователя",
"settings.usernameHint":
"Логин. 2–32 символа: строчные буквы, цифры, . _ -. Вступает в силу сразу.",
"settings.email": "Email для восстановления",
"settings.emailHint": "Необязательно. Только для отправки нового ключа.",
"settings.accent": "Акцентный цвет",
"settings.accentHint": "Применяется сразу, хранится на устройстве.",
"settings.customColor": "Свой цвет",
"settings.customAria": "Свой акцентный цвет",
"settings.accentAria": "Акцент: {label}",
"settings.featHint":
"Включайте возможности редактора. Сразу, на этом устройстве.",
"settings.providers": "Провайдеры",
"providers.intro":
"Подключите свои API-ключи. Модели подключённых провайдеров появятся в меню моделей сверху.",
"providers.hint":
"Ключи хранятся на этом сервере и больше не показываются — только последние 4 символа. Оплата идёт на ваш счёт у провайдера, политика моделей админа действует.",
"providers.connected": "Подключено",
"providers.notConnected": "Не подключено",
"providers.keyPh": "Вставьте API-ключ…",
"providers.saveKey": "Сохранить",
"providers.removeKey": "Удалить",
"providers.replaceKey": "Заменить",
"providers.getKey": "Получить ключ",
"providers.keySaved": "Ключ сохранён — модели уже в меню.",
"providers.keyRemoved": "Ключ удалён.",
"providers.invalidKey": "Похоже, ключ неверный (8–256 символов, без пробелов).",
"providers.loadFailed": "Не удалось загрузить провайдеров.",
"accent.preset.emerald": "Изумруд",
"accent.preset.rose": "Роза",
"accent.preset.blue": "Синий",
"accent.preset.violet": "Фиолет",
"accent.preset.amber": "Жёлтый",
"accent.preset.orange": "Оранжевый",
"accent.preset.teal": "Бирюза",
"accent.preset.pink": "Розовый",
"feat.thinking.label": "Размышление",
"feat.thinking.hint": "Просить модель рассуждать шаг за шагом.",
"feat.attachments.label": "Вложения",
"feat.attachments.hint": "Картинки (OCR) и текстовые файлы к сообщениям.",
"feat.deepSearch.label": "Глубокий поиск",
"feat.deepSearch.hint": "Поиск свежих источников. Скоро.",
"feat.soon": "(скоро)",
"admin.title": "Аккаунты",
"admin.intro":
"Аккаунты без KYC: создаёте имя, ключ отдаёте один раз. Хранится хэш — смена ротирует.",
"admin.keyOnce": "Ключ @{user} — показан раз, копируйте:",
"admin.newAccount": "Новый аккаунт",
"admin.email": "Email (восстановление)",
"admin.createFailed": "Не создалось",
"admin.regenFailed": "Не сменилось",
"admin.deleteFailed": "Не удалилось",
"admin.loadFailed": "Не загрузилось",
"admin.searchPh": "Поиск аккаунтов…",
"admin.searchAria": "Поиск аккаунтов",
"admin.sortAria": "Сортировка",
"admin.filterAria": "Фильтр",
"admin.sortNewest": "Сначала новые",
"admin.sortOldest": "Сначала старые",
"admin.sortAz": "А → Я",
"admin.sortZa": "Я → А",
"admin.filterAll": "Все аккаунты",
"admin.filterWith": "С email",
"admin.filterNo": "Без email",
"admin.countMany": "{total} аккаунтов · стр. {page} из {pages}",
"admin.countOne": "{total} аккаунт · стр. {page} из {pages}",
"admin.noEmail": "без email",
"admin.editProfile": "Изменить профиль",
"admin.regenKey": "Сменить ключ (убьёт сессии)",
"admin.deleteAccount": "Удалить аккаунт",
"admin.deleteTitle": "Удалить @{user}?",
"admin.deleteMsg": "Аккаунт, разговоры и ссылки удалятся навсегда.",
"admin.prevPage": "Назад",
"admin.nextPage": "Вперёд",
"ollama.models": "Модели Ollama",
"ollama.desc":
"Качайте модели на Ollama-хост или удаляйте локальные. Только админ.",
"ollama.pulling": "Качаем {name}",
"ollama.customTag": "Свой тег",
"ollama.customHint": "напр. llama3.2:3b или имя из библиотеки",
"ollama.pull": "Скачать",
"ollama.installed": "Стоит ({n})",
"ollama.noneYet": "Локальных моделей пока нет.",
"ollama.catalog": "Каталог",
"ollama.delTitle": "Удалить {name}?",
"ollama.delMsg": "Модель уйдёт с хоста. Скачайте заново когда угодно.",
"ollama.contacting": "Связь с Ollama…",
"ollama.pullingSt": "Качаем…",
"ollama.doneSt": "Готово",
"ollama.pullFailed": "Не скачалось",
"ollama.delTip": "Удалить {name}",
"ollama.sizeAria": "размер {name}",
"ollama.cat.llama3_2": "Компактная повседневная модель Meta",
"ollama.cat.llama3_1": "Рабочая лошадка Meta",
"ollama.cat.qwen2_5": "Многоязычный универсал Alibaba",
"ollama.cat.gemma2": "Эффективная открытая модель Google",
"ollama.cat.mistral": "Mistral 7B — быстрый и способный",
"ollama.cat.phi3": "Маленькая исследовательская модель Microsoft",
"ollama.cat.deepseek_r1": "Рассуждающая модель (цепочка мыслей)",
"ollama.cat.codellama": "Код и чат про код",
"ollama.cat.llava": "Зрение (понимает картинки)",
"ollama.cat.nomic_embed_text": "Текстовые эмбеддинги",
"center.title": "Админ-центр",
"center.back": "Назад в чат",
"center.tabAccounts": "Аккаунты",
"center.tabFeatures": "Функции",
"center.tabMail": "Почта",
"center.tabModels": "Модели",
"models.title": "Модели",
"models.desc": "Включайте или ограничивайте каждую модель. Отключённые модели исчезают из выбора; лимиты действуют на пользователя (админов не касаются).",
"models.refresh": "Обновить",
"models.refreshAria": "Обновить модели",
"models.enabled": "Включена",
"models.hourly": "в час",
"models.daily": "в день",
"models.unlimited": "Без лимита",
"models.ollamaTitle": "Библиотека Ollama",
"models.ollamaDesc": "Скачивание и удаление локальных моделей.",
"models.empty": "Нет доступных моделей.",
"models.saveFailed": "Не удалось сохранить",
"models.connTitle": "Подключение Ollama",
"models.connDesc": "Состояние хоста Ollama: доступность, версия, задержка и модели.",
"models.connOnline": "В сети",
"models.connOffline": "Нет связи",
"models.connDisabledState": "Отключено",
"models.connCheck": "Проверить",
"models.connCheckAria": "Проверить подключение Ollama",
"models.connHost": "Хост",
"models.connVersion": "Версия",
"models.connLatency": "Задержка",
"models.connModels": "Модели",
"models.connEmpty": "На хосте Ollama пока нет моделей — скачайте из библиотеки ниже.",
"models.connHint": "Убедитесь, что Ollama запущена и OLLAMA_HOST указывает на неё.",
"center.locked": "Только админы",
"center.lockedSub": "Войдите как админ, чтобы открыть центр.",
"center.regTitle": "Открытая регистрация",
"center.regDesc": "Кнопка регистрации на входе. Выкл = только админ создаёт. Включение закрывает лист ожидания ниже.",
"center.accTitle": "Заявки (лист ожидания)",
"center.accDescOn": "Недоступно при открытой регистрации — она заменяет.",
"center.accDescOff":
"Кнопка доступа на входе. Гости просят имя; разбор во вкладке.",
"center.ocrTitle": "Инструмент OCR",
"center.ocrDesc": "Распознавание картинок на сервере. Нужен tesseract.",
"center.reportsTitle": "Жалобы на сообщения",
"center.reportsDesc":
"Кнопка-флажок под ответами. Выкл = серый флажок с подсказкой, новые жалобы отклоняются.",
"center.usernameChangeTitle": "Смена имени",
"center.usernameChangeDesc":
"Позволяет переименоваться в Настройки → Профиль. Выкл = поле закрыто (админ всё равно может).",
"settings.usernameDisabled": "Смена имени отключена администратором.",
"center.mailTitle": "Письма восстановления",
"center.mailChecking": "Проверяем…",
"center.mailFrom": "Включено — шлём от {from}",
"center.mailDefault": "Включено — шлём с настроенного адреса",
"center.mailOff": "Выключено — задайте SMTP_HOST",
"center.mailNote":
"SMTP-доступ живёт в окружении сервера (см. docs/OPERATIONS.md), не здесь. Email задаётся в профиле или при создании.",
"center.on": "Вкл",
"center.off": "Выкл",
"share.fallback": "Общий чат",
"share.open": "Открыть KisAssistant",
"share.gone": "Этот общий чат исчез",
"share.goneSub": "Ссылка неверна, истекла или автор закрыл её.",
"share.back": "Назад",
"share.loading": "Загружаем общий чат…",
"share.by": "от {name}",
"reset.checking": "Проверяем ссылку…",
"reset.invalid": "Ссылка неверна",
"reset.invalidSub":
"Ссылка неизвестна, использована или истекла. Запросите новую на входе.",
"reset.readyTitle": "Новый ключ для @{user}?",
"reset.readySub": "Сразу выдадим свежий ключ. Старый перестанет работать.",
"reset.issue": "Выдать ключ",
"reset.issuing": "Выдаём…",
"reset.doneTitle": "Ключ готов",
"reset.doneSub": "Скопируйте сейчас — больше не покажем. Войдите с ним.",
"reset.goLogin": "Ко входу",
"reset.failed": "Не вышло",
"app.deleteConvTitle": "Удалить разговор?",
"app.deleteConvMsg": "«{title}» и сообщения удалятся.",
"settings.language": "Язык",
"settings.languageHint": "Язык интерфейса. Сразу, на этом устройстве.",
"settings.security": "Безопасность",
"sec.accessKey": "Ключ доступа",
"sec.accessKeyHint":
"Смените ключ. Старые сессии отзовутся сразу — войдёте с новым.",
"sec.rotate": "Сменить мой ключ",
"sec.rotateConfirm": "Нажмите ещё раз для подтверждения",
"sec.rotationFailed": "Не сменилось",
"sec.totp": "Двухфакторка (TOTP)",
"sec.totpChecking": "Проверяем…",
"sec.totpAddHint":
"Добавьте 6-значный код из приложения поверх ключа.",
"sec.totpEnable": "Включить двухфакторку",
"sec.totpSecretHint":
"Добавьте секрет в приложение (или откройте otpauth-ссылку) и введите код:",
"sec.totpConfirm": "Подтвердить",
"sec.totpDisableLabel": "Отключить текущим кодом",
"sec.totpDisable": "Выключить 2FA",
"sec.setupFailed": "Не настроилось",
"sec.passkeys": "Пасскеи",
"sec.passkeysHint":
"WebAuthn / системные ключи — нужен RP на сервере.",
"sec.danger": "Опасная зона",
"sec.dangerHint":
"Навсегда удалит аккаунт с чатами, ссылками и сессиями. Без возврата.",
"sec.deleteMe": "Удалить мой аккаунт",
"sec.deleteFailed": "Не удалилось",
"sec.newKeyTitle": "Новый ключ доступа",
"sec.newKeyHint":
"Скопируйте сейчас — больше не покажем. Старые сессии отозваны.",
"sec.newKeyDone": "Готово — выйти",
"sec.deleteTitle": "Удалить ваш аккаунт?",
"sec.deleteMsg":
"Навсегда удалит аккаунт с разговорами, ссылками и сессиями. Без возврата.",
"sec.deleteForever": "Удалить навсегда",
"sec.avatarTooBig": "Файл слишком большой (макс. 5 МБ).",
"sec.avatarType": "Только картинки jpg, png или webp.",
"center.tabAccess": "Доступ",
"center.smtpHost": "Хост",
"center.smtpPort": "Порт",
"center.smtpUser": "Пользователь",
"center.smtpPass": "Пароль",
"center.smtpFrom": "Отправитель",
"center.smtpAppUrl": "URL приложения",
"center.notSet": "(не задано)",
"center.noAuth": "(без auth)",
"center.tlsImplicit": "неявный TLS (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Показать пароль SMTP",
"center.hidePass": "Скрыть пароль SMTP",
"center.hiddenPass": "пароль скрыт",
"center.mailTestTitle": "Проверка связи",
"center.mailTestDesc":
"Проверьте соединение и отправьте тестовое письмо на свой адрес.",
"center.verifyConn": "Проверить соединение",
"center.verifying": "Проверяем…",
"center.sendTest": "Отправить тест",
"center.sendingMail": "Отправляем…",
"center.testToAria": "Адрес для теста",
"center.connOk": "Связь OK — SMTP доступен, auth принят.",
"center.verifyFailed": "Проверка не удалась",
"center.testSent": "Тест отправлен на {to}{tail}.",
"center.mailSendFailed": "Не отправилось",
"center.credsNote":
"Доступы живут в окружении сервера (см. docs/OPERATIONS.md), здесь только чтение. Email задаётся в профиле или при создании.",
"access.status.pending": "Ожидает",
"access.status.reviewing": "На проверке",
"access.status.accepted": "Принята",
"access.status.refused": "Отклонена",
"access.filter.all": "все",
"access.filter.pending": "ожидают",
"access.filter.reviewing": "на проверке",
"access.filter.accepted": "приняты",
"access.filter.refused": "отклонены",
"access.refresh": "Обновить",
"access.refreshAria": "Обновить заявки",
"access.empty": "Заявок нет. Лист ожидания пуст.",
"access.emptyFiltered": "С таким статусом ничего нет.",
"access.msgOne": "1 сообщение",
"access.msgMany": "{n} сообщений",
"access.accountCreated": "Аккаунт создан — ключ показан раз, копируйте:",
"access.replyPh": "Ответить (уйдёт по email)…",
"access.replyAria": "Ответить заявителю",
"access.reasonLabel": "Причина (уйдёт с решением)",
"access.reasonPh": "Необязательная причина…",
"access.btnReviewing": "На проверку",
"access.btnAccept": "Принять",
"access.btnRefuse": "Отклонить",
"access.closedNote": "Тикет закрыт ({status}).",
"access.reasonWord": "Причина",
"access.youAdmin": "Вы (админ)",
"access.sendFailed": "Не отправилось",
"access.updateFailed": "Не обновилось",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Скопировать сообщение",
"msg.search": "Искать в интернете",
"msg.report": "Пожаловаться на ответ",
"msg.reportDisabled": "Жалобы отключены",
"msg.retry": "Повторить",
"report.title": "Пожаловаться на этот ответ",
"report.reason": "Причина",
"report.reasonPh": "Выберите причину…",
"report.reason.copyright": "Авторские права",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "Ложная информация",
"report.reason.bug": "Ошибка",
"report.details": "Подробности (необязательно)",
"report.detailsPh": "Что не так с этим ответом? (необязательно)",
"report.submit": "Отправить жалобу",
"report.sent": "Жалоба отправлена — администратор её рассмотрит.",
"report.failed": "Не удалось отправить жалобу",
"center.tabReports": "Жалобы",
"reports.filter.all": "все",
"reports.filter.open": "открытые",
"reports.filter.reviewing": "на рассмотрении",
"reports.filter.resolved": "решённые",
"reports.filter.dismissed": "отклонённые",
"reports.status.open": "Открыта",
"reports.status.reviewing": "На рассмотрении",
"reports.status.resolved": "Решена",
"reports.status.dismissed": "Отклонена",
"reports.refresh": "Обновить",
"reports.refreshAria": "Обновить жалобы",
"reports.empty": "Жалоб на контент пока нет.",
"reports.emptyFiltered": "Ничего с этим статусом.",
"reports.response": "Ответ",
"reports.noContent": "Содержимое отсутствует.",
"reports.model": "Модель",
"reports.reporter": "Автор жалобы",
"reports.conversation": "Беседа",
"reports.detailsGiven": "Комментарий автора",
"reports.noteLabel": "Заметка админа",
"reports.notePh": "Внутренняя заметка…",
"reports.noteWord": "Заметка",
"reports.btnReviewing": "На рассмотрение",
"reports.btnResolve": "Решить",
"reports.btnDismiss": "Отклонить",
"reports.updateFailed": "Не обновилось",
"reports.closedNote": "Жалоба {status}.",
"report.alreadyReported": "На этот ответ уже пожаловались.",
"reports.prompt": "Запрос пользователя",
"reports.unreliable": "Ненадёжный автор",
"reports.shadowban": "Теневой бан",
"reports.unshadowban": "Снять теневой бан",
"reports.shadowbanTitle": "Теневой бан для этого автора?",
"reports.shadowbanMsg": "Жалобы @{user} будут приниматься, но помечаться как ненадёжные и не учитываться в счётчике.",
"reports.unshadowbanTitle": "Снять теневой бан?",
"reports.unshadowbanMsg": "Жалобы @{user} снова будут учитываться.",
"review.title": "Заявка на доступ",
"review.loadingTicket": "Загружаем тикет…",
"review.notFound": "Тикет не найден",
"review.notFoundSub":
"Ссылка неизвестна. Проверьте URL из письма или подайте заявку со входа.",
"review.adminNote": "Заметка админа:",
"review.acceptedHint":
"Аккаунт создан — проверьте письмо с ключом и входите.",
"review.closedHint":
"Тикет закрыт. Письма не читаются — при нужде подайте новую заявку.",
"review.replyPh": "Изложите свой случай…",
"review.replyAria": "Ответить в тикет",
"review.mailHint":
"Письма — в одну сторону: отвечайте здесь, не по email.",
"review.status.pending": "Ждёт проверки",
"review.status.reviewing": "На проверке",
"review.status.accepted": "Принята",
"review.status.refused": "Отклонена",
"review.admin": "Админ",
"review.you": "Вы",
"review.requestTitle": "Запросить доступ",
"review.requestIntro":
"Займите имя и расскажите, зачем вам сюда. Админ разберёт каждую заявку — следите за тикетом и почтой.",
"review.emailHint": "Обязательно — статусы и ответы придут сюда.",
"review.whyLabel": "Почему вам дать доступ?",
"review.whyHint": "10+ символов. Это откроет тикет.",
"review.whyPh": "Я хочу…",
"review.emailLabel": "Email",
"review.sendRequest": "Отправить заявку",
"review.received": "Заявка получена",
"review.reserved":
"@{user} занято вами, пока админ проверяет. Письмо с тикетом уже летит.",
"review.copyLink": "Копировать ссылку",
"review.openTicket": "Открыть мой тикет",
"admin.editUserTitle": "Править @{user}",
"admin.avatarUrl": "URL аватара",
"archived.readonly": "Чат в архиве, только чтение.",
"archived.unarchive": "Вернуть",
"archived.title": "Архив чатов",
"archived.empty": "Нет архивных чатов.",
"archived.view": "Открыть",
"archived.deleteTitle": "Удалить этот архивный чат?",
"archived.deleteMsg": "Это навсегда удалит разговор и все сообщения.",
};
const it: Dict = {
"common.close": "Chiudi",
"common.cancel": "Annulla",
"common.save": "Salva",
"common.done": "Fatto",
"common.copy": "Copia",
"common.copied": "Copiato",
"common.create": "Crea",
"common.delete": "Elimina",
"common.loading": "Caricamento…",
"common.saving": "Salvataggio…",
"common.username": "Nome utente",
"common.displayName": "Nome visualizzato",
"common.select": "Scegli…",
"common.theme": "Tema",
"common.themeAuto": "Auto",
"common.themeAutoFull": "Auto (segue il sistema)",
"common.themeSunset": "Tramonto",
"common.themeSunsetFull": "Tramonto (ora locale)",
"common.light": "Chiaro",
"common.dark": "Scuro",
"common.saveFailed": "Salvataggio non riuscito",
"common.loadFailed": "Caricamento fallito",
"common.deleteFailed": "Eliminazione fallita",
"common.backToLogin": "Torna al login",
"loading.tagline": "Preparo le tue chat",
"login.welcome": "Bentornato",
"login.subtitle": "Accedi a KisAssistant per continuare",
"login.usernamePh": "Nome utente",
"login.keyPh": "Chiave di accesso",
"login.failed": "Accesso non riuscito",
"login.unlock": "Sblocca",
"login.newHere": "Nuovo qui?",
"login.register": "Registrati",
"login.regTipOn": "Crea un account",
"login.regTipOff": "Registrazione disattivata su questa piattaforma",
"login.requestAccess": "Richiedi accesso",
"login.forgot": "Chiave dimenticata?",
"login.perk1": "Privato per progettazione — niente cookie né traccianti",
"login.perk2": "I tuoi modelli, in tempo reale",
"login.adminNotePre": "La chiave admin vive nel .env del server",
"login.adminNotePost": "; le chiavi utente le emette l'admin.",
"login.totpIntro": "Doppio fattore per @{user} — inserisci il codice a 6 cifre dall'app.",
"login.totpAria": "Codice autenticatore",
"login.totpInvalid": "Codice non valido",
"login.verify": "Verifica",
"sidebar.newChat": "Nuova chat",
"sidebar.collapse": "Nascondi barra laterale",
"sidebar.closeDrawer": "Chiudi chat",
"sidebar.searchPh": "Cerca chat…",
"sidebar.searchAria": "Cerca conversazioni",
"sidebar.clearSearch": "Cancella ricerca",
"sidebar.searching": "Ricerca…",
"sidebar.noMatch": "Nessun risultato per «{q}».",
"sidebar.youPrefix": "tu: ",
"sidebar.emptyA": "Nessuna conversazione.",
"sidebar.emptyB": "Inizia una nuova chat qui sopra.",
"sidebar.rename": "Rinomina",
"sidebar.topic": "Imposta argomento",
"sidebar.share": "Condividi pubblicamente",
"sidebar.delete": "Elimina",
"sidebar.convOptions": "Opzioni conversazione",
"sidebar.admin": "admin",
"sidebar.adminCenter": "Centro admin",
"sidebar.adminCenterTip": "Apri il Centro admin",
"sidebar.settingsTip": "Profilo e impostazioni",
"sidebar.logout": "Esci",
"sidebar.archive": "Archivia",
"chat.expand": "Mostra barra laterale",
"chat.openNav": "Apri chat",
"chat.modelAria": "Modello",
"chat.noModels": "Nessun modello",
"chat.selectModel": "Scegli modello…",
"chat.personalTag": "chiave personale",
"toast.chatDeleted": "Chat “{title}” eliminata",
"toast.chatArchived": "Chat “{title}” archiviata",
"toast.chatUnarchived": "Chat “{title}” disarchiviata",
"toast.modelChanged": "Modello: {label}",
"toast.themeChanged": "Tema cambiato",
"toast.accentChanged": "Colore accento cambiato",
"toast.unshared": "Link condiviso rimosso",
"toast.settingsSaved": "Impostazioni salvate",
"toast.convUpdated": "Conversazione “{title}” aggiornata",
"chat.you": "Tu",
"chat.greet": "Come posso aiutare, {name}?",
"chat.greetSub": "Scegli un modello e scrivi qui sotto. Markdown supportato.",
"chat.thinking": "Penso…",
"chat.placeholder": "Scrivi a KisAssistant…",
"chat.send": "Invia",
"chat.attachTip": "Allega un file",
"chat.removeAttach": "Rimuovi {name}",
"chat.ocrOpt": "Trascrivi immagine",
"chat.unavailable": "(non disponibile)",
"chat.ocrHint": "JPG, PNG, WEBP — OCR sul server, rivedi il testo prima",
"chat.textOpt": "Allega file di testo",
"chat.textHint": "TXT o Markdown, max 500KB",
"chat.attachNote":
"Upload solo con gli strumenti della piattaforma. Le immagini arrivano al modello come testo rivisto — mai grezze.",
"chat.wiki": "Wiki e docs",
"attach.tooBigImg": "Immagine troppo grande (max 5MB).",
"attach.tooBigText": "File troppo grande (max 500KB).",
"attach.uploadFailed": "Upload non riuscito",
"attach.kindOcr": "trascrizione immagine",
"attach.kindText": "file di testo",
"attach.tpl": "[allegato {kind}: {name}]",
"attach.chatError": "**Errore:** il modello non ha risposto. Riprova.",
"dlg.editConv": "Modifica conversazione",
"dlg.fTitle": "Titolo",
"dlg.fTopic": "Argomento",
"dlg.topicHint": "Breve etichetta, es. cucina, rust, viaggi.",
"dlg.noTopic": "Nessun argomento",
"dlg.recoverTitle": "Recupera chiave di accesso",
"dlg.recoverIntro":
"Inserisci il tuo nome utente. Riceverai un link che emette una chiave nuova (la vecchia smette di funzionare).",
"dlg.sendLink": "Invia link",
"dlg.reqFailed": "Richiesta fallita",
"dlg.recoverSent":
"Se @{user} esiste con email di recupero, un link è in viaggio{fromPart} (valido 60 minuti, monouso).",
"dlg.recoverSentFrom": " da {from}",
"dlg.spamNote": "Controlla la posta — e lo spam, potrebbe essere finito lì.",
"dlg.noMailNote":
"Nulla in arrivo? Allora nessuna email è impostata e non si può — contatta l'amministratore del sito.",
"dlg.registerTitle": "Crea un account",
"dlg.regWelcome":
"Benvenuto, @{user}! La tua chiave — copiala ora, non sarà più mostrata.",
"dlg.regContinue": "Copia e vai al login",
"dlg.regFailed": "Registrazione fallita",
"dlg.emailOpt": "Email (opzionale, per recupero chiave)",
"dlg.shareTitle": "Condividi pubblicamente",
"dlg.shareCreating": "Creazione link pubblico…",
"dlg.shareIntro":
"Chiunque abbia questo link può leggere {title}. Senza login.",
"dlg.unshare": "Rimuovi condivisione",
"dlg.reviewOcr": "Rivedi trascrizione",
"dlg.reviewText": "Rivedi allegato",
"dlg.transcribing": "Trascrizione immagine sul server (OCR)…",
"dlg.uploadingTools": "Upload con gli strumenti…",
"dlg.ocrExpl":
"L'immagine è stata trascritta in testo sul server — il modello riceve questo testo, mai l'immagine. Correggi sotto e allega.",
"dlg.textExpl":
"Il file è stato caricato con gli strumenti. Il suo testo sarà allegato al messaggio. Modifica e allega.",
"dlg.truncWarn": "Trascrizione troncata al limite server — manca la fine.",
"dlg.attachBtn": "Allega al messaggio",
"dlg.chars": "{n} caratteri",
"settings.title": "Impostazioni",
"settings.searchPh": "Cerca impostazioni…",
"settings.searchAria": "Cerca impostazioni",
"settings.clearSearch": "Cancella ricerca",
"settings.noMatch": "Nessuna impostazione per «{q}».",
"settings.profile": "Profilo",
"settings.appearance": "Aspetto",
"settings.features": "Funzioni",
"settings.avatarUpload": "Carica avatar",
"settings.dropIdle": "Trascina un'immagine o clicca per caricare",
"settings.dropActive": "Lascia!",
"settings.uploading": "Caricamento…",
"settings.avatarHint": "jpg · png · webp — max 5MB — 5 cambi per 2h",
"settings.username": "Nome utente",
"settings.usernameHint":
"Nome di accesso. 2–32 caratteri: minuscole, cifre, . _ -. Effetto immediato.",
"settings.email": "Email di recupero",
"settings.emailHint": "Opzionale. Solo per inviarti una chiave nuova.",
"settings.accent": "Colore accento",
"settings.accentHint": "Subito attivo, salvato su questo dispositivo.",
"settings.customColor": "Colore custom",
"settings.customAria": "Colore accento personalizzato",
"settings.accentAria": "Accento: {label}",
"settings.featHint":
"Attiva funzioni del composer. Subito, su questo dispositivo.",
"settings.providers": "Provider",
"providers.intro":
"Collega le tue chiavi API. I modelli dei provider collegati appaiono nel menu dei modelli in alto.",
"providers.hint":
"Le chiavi restano su questo server e non vengono più mostrate — solo gli ultimi 4 caratteri. L'uso è addebitato al tuo account e resta valida la policy modelli dell'admin.",
"providers.connected": "Collegato",
"providers.notConnected": "Non collegato",
"providers.keyPh": "Incolla la chiave API…",
"providers.saveKey": "Salva",
"providers.removeKey": "Rimuovi",
"providers.replaceKey": "Sostituisci",
"providers.getKey": "Ottieni chiave",
"providers.keySaved": "Chiave salvata — i modelli sono nel menu.",
"providers.keyRemoved": "Chiave rimossa.",
"providers.invalidKey": "Chiave non valida (8–256 caratteri, senza spazi).",
"providers.loadFailed": "Impossibile caricare i provider.",
"accent.preset.emerald": "Smeraldo",
"accent.preset.rose": "Rosa",
"accent.preset.blue": "Blu",
"accent.preset.violet": "Viola",
"accent.preset.amber": "Giallo",
"accent.preset.orange": "Arancione",
"accent.preset.teal": "Teal",
"accent.preset.pink": "Rosa shocking",
"feat.thinking.label": "Ragionamento",
"feat.thinking.hint": "Chiedi al modello di ragionare passo passo.",
"feat.attachments.label": "Allegati",
"feat.attachments.hint":
"Allega immagini (trascrizione OCR) e file di testo.",
"feat.deepSearch.label": "Ricerca profonda",
"feat.deepSearch.hint": "Cerca fonti fresche sul web. Prossimamente.",
"feat.soon": "(presto)",
"admin.title": "Account",
"admin.intro":
"Account senza KYC: crei un nome, consegni la chiave una volta. Hash salvati — rigenera per ruotare.",
"admin.keyOnce": "Chiave per @{user} — mostrata una volta, copiala ora:",
"admin.newAccount": "Nuovo account",
"admin.email": "Email (recupero)",
"admin.createFailed": "Creazione fallita",
"admin.regenFailed": "Rigenerazione fallita",
"admin.deleteFailed": "Eliminazione fallita",
"admin.loadFailed": "Caricamento fallito",
"admin.searchPh": "Cerca account…",
"admin.searchAria": "Cerca account",
"admin.sortAria": "Ordina account",
"admin.filterAria": "Filtra account",
"admin.sortNewest": "Più recenti",
"admin.sortOldest": "Meno recenti",
"admin.sortAz": "A → Z",
"admin.sortZa": "Z → A",
"admin.filterAll": "Tutti gli account",
"admin.filterWith": "Con email di recupero",
"admin.filterNo": "Senza email di recupero",
"admin.countMany": "{total} account · pagina {page} di {pages}",
"admin.countOne": "{total} account · pagina {page} di {pages}",
"admin.noEmail": "senza email di recupero",
"admin.editProfile": "Modifica profilo",
"admin.regenKey": "Rigenera chiave (revoca sessioni)",
"admin.deleteAccount": "Elimina account",
"admin.deleteTitle": "Eliminare @{user}?",
"admin.deleteMsg":
"Rimuove per sempre account, conversazioni e condivisioni.",
"admin.prevPage": "Pagina precedente",
"admin.nextPage": "Pagina successiva",
"ollama.models": "Modelli Ollama",
"ollama.desc":
"Scarica modelli sull'host Ollama o rimuovi i locali. Solo admin.",
"ollama.pulling": "Scarico {name}",
"ollama.customTag": "Tag personalizzato",
"ollama.customHint": "es. llama3.2:3b, o un nome di libreria",
"ollama.pull": "Scarica",
"ollama.installed": "Installati ({n})",
"ollama.noneYet": "Ancora nessun modello locale.",
"ollama.catalog": "Catalogo",
"ollama.delTitle": "Eliminare {name}?",
"ollama.delMsg": "Il modello lascia l'host Ollama. Riscaricalo quando vuoi.",
"ollama.contacting": "Contatto Ollama…",
"ollama.pullingSt": "Scarico…",
"ollama.doneSt": "Fatto",
"ollama.pullFailed": "Download fallito",
"ollama.delTip": "Elimina {name}",
"ollama.sizeAria": "taglia di {name}",
"ollama.cat.llama3_2": "Il compatto Meta per tutti i giorni",
"ollama.cat.llama3_1": "Il cavallo di battaglia Meta",
"ollama.cat.qwen2_5": "Multilingua Alibaba tuttofare",
"ollama.cat.gemma2": "L'open efficiente di Google",
"ollama.cat.mistral": "Mistral 7B — veloce e capace",
"ollama.cat.phi3": "Il piccolo modello Microsoft",
"ollama.cat.deepseek_r1": "Modello di ragionamento (catena di pensiero)",
"ollama.cat.codellama": "Completamento e chat di codice",
"ollama.cat.llava": "Visione (capisce le immagini)",
"ollama.cat.nomic_embed_text": "Embedding di testo",
"center.title": "Centro admin",
"center.back": "Torna alla chat",
"center.tabAccounts": "Account",
"center.tabFeatures": "Funzioni",
"center.tabMail": "Mail",
"center.tabModels": "Modelli",
"models.title": "Modelli",
"models.desc": "Abilita o limita ogni modello. I modelli disabilitati spariscono dal selettore; i limiti valgono per utente (gli admin sono esenti).",
"models.refresh": "Aggiorna",
"models.refreshAria": "Aggiorna modelli",
"models.enabled": "Abilitato",
"models.hourly": "all'ora",
"models.daily": "al giorno",
"models.unlimited": "Illimitato",
"models.ollamaTitle": "Libreria Ollama",
"models.ollamaDesc": "Scarica o rimuovi modelli locali.",
"models.empty": "Nessun modello disponibile.",
"models.saveFailed": "Salvataggio fallito",
"models.connTitle": "Connettività Ollama",
"models.connDesc": "Stato live dell'host Ollama: raggiungibilità, versione, latenza e modelli installati.",
"models.connOnline": "Online",
"models.connOffline": "Offline",
"models.connDisabledState": "Disabilitato",
"models.connCheck": "Verifica ora",
"models.connCheckAria": "Verifica la connettività Ollama",
"models.connHost": "Host",
"models.connVersion": "Versione",
"models.connLatency": "Latenza",
"models.connModels": "Modelli",
"models.connEmpty": "Nessun modello sull'host Ollama — scaricane uno dalla libreria qui sotto.",
"models.connHint": "Assicurati che Ollama sia in esecuzione e che OLLAMA_HOST punti a esso.",
"center.locked": "Solo admin",
"center.lockedSub": "Accedi come admin per aprire il Centro.",
"center.regTitle": "Registrazione pubblica",
"center.regDesc": "Mostra Registrati al login. Off = solo account admin. Attivarlo ritira la wishlist qui sotto.",
"center.accTitle": "Richieste di accesso (lista)",
"center.accDescOn":
"Non disponibile con registrazione pubblica — la sostituisce.",
"center.accDescOff":
"Mostra Richiedi accesso al login. Valuta nella scheda Accesso.",
"center.ocrTitle": "Strumento OCR",
"center.ocrDesc": "Trascrizione immagini sul server. Serve tesseract.",
"center.reportsTitle": "Segnalazioni messaggi",
"center.reportsDesc":
"Bandierina sotto le risposte. Off = bandierina grigia con tooltip e nuove segnalazioni rifiutate.",
"center.usernameChangeTitle": "Cambi di nome",
"center.usernameChangeDesc":
"Permette di rinominarsi in Impostazioni → Profilo. Off = campo bloccato (l'admin può ancora rinominare).",
"settings.usernameDisabled": "Cambi di nome disabilitati dall'amministratore.",
"center.mailTitle": "Email di recupero",
"center.mailChecking": "Verifica…",
"center.mailFrom": "Attivo — inviate da {from}",
"center.mailDefault": "Attivo — inviate dal mittente configurato",
"center.mailOff": "Disattivo — imposta SMTP_HOST sul server",
"center.mailNote":
"Le credenziali SMTP vivono sul server (vedi docs/OPERATIONS.md), mai qui. L'email si imposta nel profilo o alla creazione.",
"center.on": "Sì",
"center.off": "No",
"share.fallback": "Chat condivisa",
"share.open": "Apri KisAssistant",
"share.gone": "Questa chat condivisa non c'è più",
"share.goneSub": "Il link non vale, è scaduto o l'autore l'ha tolto.",
"share.back": "Indietro",
"share.loading": "Carico chat condivisa…",
"share.by": "di {name}",
"reset.checking": "Verifica link…",
"reset.invalid": "Link non valido",
"reset.invalidSub":
"Link sconosciuto, usato o scaduto. Richiedine uno al login.",
"reset.readyTitle": "Nuova chiave per @{user}?",
"reset.readySub":
"Emette subito una chiave nuova. La vecchia smette di funzionare.",
"reset.issue": "Emetti nuova chiave",
"reset.issuing": "Emissione…",
"reset.doneTitle": "Nuova chiave pronta",
"reset.doneSub": "Copiala ora — non sarà più mostrata. Accedi con essa.",
"reset.goLogin": "Vai al login",
"reset.failed": "Recupero fallito",
"app.deleteConvTitle": "Eliminare conversazione?",
"app.deleteConvMsg": "«{title}» e i suoi messaggi saranno eliminati.",
"settings.language": "Lingua",
"settings.languageHint":
"Lingua dell'interfaccia. Subito, su questo dispositivo.",
"settings.security": "Sicurezza",
"sec.accessKey": "Chiave di accesso",
"sec.accessKeyHint":
"Ruota la tua chiave. Le vecchie sessioni sono revocate subito — rientri con la nuova.",
"sec.rotate": "Ruota la mia chiave",
"sec.rotateConfirm": "Clicca di nuovo per confermare",
"sec.rotationFailed": "Rotazione fallita",
"sec.totp": "Doppio fattore (TOTP)",
"sec.totpChecking": "Verifica…",
"sec.totpAddHint":
"Aggiungi un codice a 6 cifre dall'app oltre alla chiave.",
"sec.totpEnable": "Attiva doppio fattore",
"sec.totpSecretHint":
"Aggiungi questo segreto all'app (o apri il link otpauth) e inserisci un codice:",
"sec.totpConfirm": "Conferma",
"sec.totpDisableLabel": "Disattiva con un codice attuale",
"sec.totpDisable": "Disattiva 2FA",
"sec.setupFailed": "Configurazione fallita",
"sec.passkeys": "Passkey",
"sec.passkeysHint":
"WebAuthn / autenticatori di sistema — serve RP sul server.",
"sec.danger": "Zona pericolosa",
"sec.dangerHint":
"Elimina account con chat, condivisioni e sessioni. Irreversibile.",
"sec.deleteMe": "Elimina il mio account",
"sec.deleteFailed": "Eliminazione fallita",
"sec.newKeyTitle": "Nuova chiave di accesso",
"sec.newKeyHint":
"Copiala ora — non sarà più mostrata. Le vecchie sessioni sono revocate.",
"sec.newKeyDone": "Fatto — esci",
"sec.deleteTitle": "Eliminare il tuo account?",
"sec.deleteMsg":
"Rimuove per sempre account con conversazioni, condivisioni e sessioni. Irreversibile.",
"sec.deleteForever": "Elimina per sempre",
"sec.avatarTooBig": "File troppo grande (max 5MB).",
"sec.avatarType": "Solo immagini jpg, png o webp.",
"center.tabAccess": "Accesso",
"center.smtpHost": "Host",
"center.smtpPort": "Porta",
"center.smtpUser": "Utente",
"center.smtpPass": "Password",
"center.smtpFrom": "Mittente",
"center.smtpAppUrl": "URL dell'app",
"center.notSet": "(non impostato)",
"center.noAuth": "(senza auth)",
"center.tlsImplicit": "TLS implicito (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Mostra password SMTP",
"center.hidePass": "Nascondi password SMTP",
"center.hiddenPass": "password nascosta",
"center.mailTestTitle": "Test di connessione",
"center.mailTestDesc":
"Verifica la connessione e invia una vera mail di test a un tuo indirizzo.",
"center.verifyConn": "Verifica connessione",
"center.verifying": "Verifica…",
"center.sendTest": "Invia mail di test",
"center.sendingMail": "Invio…",
"center.testToAria": "Email di test",
"center.connOk": "Connessione OK — host SMTP raggiungibile, auth accettata.",
"center.verifyFailed": "Verifica fallita",
"center.testSent": "Mail di test inviata a {to}{tail}.",
"center.mailSendFailed": "Invio fallito",
"center.credsNote":
"Le credenziali vivono sul server (vedi docs/OPERATIONS.md), qui sola lettura. L'email si imposta nel profilo o alla creazione.",
"access.status.pending": "In attesa",
"access.status.reviewing": "In revisione",
"access.status.accepted": "Accettata",
"access.status.refused": "Rifiutata",
"access.filter.all": "tutti",
"access.filter.pending": "in attesa",
"access.filter.reviewing": "in revisione",
"access.filter.accepted": "accettati",
"access.filter.refused": "rifiutati",
"access.refresh": "Aggiorna",
"access.refreshAria": "Aggiorna richieste",
"access.empty": "Nessuna richiesta. La lista è vuota.",
"access.emptyFiltered": "Nulla con questo stato.",
"access.msgOne": "1 messaggio",
"access.msgMany": "{n} messaggi",
"access.accountCreated": "Account creato — chiave unica, copiala ora:",
"access.replyPh": "Rispondi (arriva via email)…",
"access.replyAria": "Rispondi al richiedente",
"access.reasonLabel": "Motivo (inviato con la decisione)",
"access.reasonPh": "Motivo opzionale…",
"access.btnReviewing": "In revisione",
"access.btnAccept": "Accetta",
"access.btnRefuse": "Rifiuta",
"access.closedNote": "Ticket chiuso ({status}).",
"access.reasonWord": "Motivo",
"access.youAdmin": "Tu (admin)",
"access.sendFailed": "Invio fallito",
"access.updateFailed": "Aggiornamento fallito",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Copia messaggio",
"msg.search": "Cerca nel web",
"msg.report": "Segnala risposta",
"msg.reportDisabled": "Segnalazioni disabilitate",
"msg.retry": "Riprova",
"report.title": "Segnala questa risposta",
"report.reason": "Motivo",
"report.reasonPh": "Seleziona un motivo…",
"report.reason.copyright": "Diritto d'autore",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "Informazione falsa",
"report.reason.bug": "Bug",
"report.details": "Dettagli (facoltativo)",
"report.detailsPh": "Cosa c'è di sbagliato in questa risposta? (facoltativo)",
"report.submit": "Invia segnalazione",
"report.sent": "Segnalazione inviata — un amministratore la esaminerà.",
"report.failed": "Impossibile inviare la segnalazione",
"center.tabReports": "Segnalazioni",
"reports.filter.all": "tutte",
"reports.filter.open": "aperte",
"reports.filter.reviewing": "in revisione",
"reports.filter.resolved": "risolte",
"reports.filter.dismissed": "respinte",
"reports.status.open": "Aperta",
"reports.status.reviewing": "In revisione",
"reports.status.resolved": "Risolta",
"reports.status.dismissed": "Respinta",
"reports.refresh": "Aggiorna",
"reports.refreshAria": "Aggiorna segnalazioni",
"reports.empty": "Nessuna segnalazione ancora.",
"reports.emptyFiltered": "Niente con questo stato.",
"reports.response": "Risposta segnalata",
"reports.noContent": "Nessun contenuto acquisito.",
"reports.model": "Modello",
"reports.reporter": "Autore",
"reports.conversation": "Conversazione",
"reports.detailsGiven": "Dettagli dell'autore",
"reports.noteLabel": "Nota admin",
"reports.notePh": "Nota interna…",
"reports.noteWord": "Nota",
"reports.btnReviewing": "In revisione",
"reports.btnResolve": "Risolvi",
"reports.btnDismiss": "Respingi",
"reports.updateFailed": "Aggiornamento fallito",
"reports.closedNote": "Segnalazione {status}.",
"report.alreadyReported": "Questa risposta è già stata segnalata.",
"reports.prompt": "Richiesta dell'utente",
"reports.unreliable": "Autore inaffidabile",
"reports.shadowban": "Silenzia autore",
"reports.unshadowban": "Togli silenzio",
"reports.shadowbanTitle": "Silenziare questo autore?",
"reports.shadowbanMsg": "Le segnalazioni di @{user} saranno comunque accettate ma marcate come inaffidabili ed escluse dal conteggio.",
"reports.unshadowbanTitle": "Togliere il silenzio?",
"reports.unshadowbanMsg": "Le segnalazioni di @{user} conteranno di nuovo.",
"review.title": "Richiesta di accesso",
"review.loadingTicket": "Carico ticket…",
"review.notFound": "Ticket non trovato",
"review.notFoundSub":
"Link sconosciuto. Controlla l'URL della tua email o richiedi accesso dal login.",
"review.adminNote": "Nota admin:",
"review.acceptedHint":
"Account creato — controlla l'email con la chiave e accedi.",
"review.closedHint":
"Ticket chiuso. Le email non si leggono — se serve, richiedi di nuovo.",
"review.replyPh": "Perora la tua causa…",
"review.replyAria": "Rispondi al tuo ticket",
"review.mailHint":
"Le email sono a senso unico — rispondi qui, non via email.",
"review.status.pending": "In attesa di revisione",
"review.status.reviewing": "In revisione",
"review.status.accepted": "Accettata",
"review.status.refused": "Rifiutata",
"review.admin": "Admin",
"review.you": "Tu",
"review.requestTitle": "Richiedi accesso",
"review.requestIntro":
"Riserva un nome e spiega perché vuoi entrare. Un admin valuta ogni richiesta — segui il filo sul tuo ticket e via email.",
"review.emailHint": "Obbligatoria — avvisi e risposte arrivano qui.",
"review.whyLabel": "Perché darti accesso?",
"review.whyHint": "10+ caratteri. Questo apre il tuo ticket.",
"review.whyPh": "Voglio…",
"review.emailLabel": "Email",
"review.sendRequest": "Invia richiesta",
"review.received": "Richiesta ricevuta",
"review.reserved":
"@{user} è riservato mentre un admin valuta. Un'email col tuo ticket è in viaggio.",
"review.copyLink": "Copia link",
"review.openTicket": "Apri il mio ticket",
"admin.editUserTitle": "Modifica @{user}",
"admin.avatarUrl": "URL avatar",
"archived.readonly": "Questa chat è archiviata e in sola lettura.",
"archived.unarchive": "Ripristina",
"archived.title": "Chat archiviate",
"archived.empty": "Nessuna conversazione archiviata.",
"archived.view": "Vedi",
"archived.deleteTitle": "Eliminare questa chat archiviata?",
"archived.deleteMsg": "Questo rimuove definitivamente la conversazione e tutti i suoi messaggi.",
};
const pt: Dict = {
"common.close": "Fechar",
"common.cancel": "Cancelar",
"common.save": "Guardar",
"common.done": "Pronto",
"common.copy": "Copiar",
"common.copied": "Copiado",
"common.create": "Criar",
"common.delete": "Eliminar",
"common.loading": "A carregar…",
"common.saving": "A guardar…",
"common.username": "Nome de utilizador",
"common.displayName": "Nome visível",
"common.select": "Escolher…",
"common.theme": "Tema",
"common.themeAuto": "Auto",
"common.themeAutoFull": "Auto (segue o sistema)",
"common.themeSunset": "Pôr do sol",
"common.themeSunsetFull": "Pôr do sol (hora local)",
"common.light": "Claro",
"common.dark": "Escuro",
"common.saveFailed": "Falha ao guardar",
"common.loadFailed": "Falha ao carregar",
"common.deleteFailed": "Falha ao eliminar",
"common.backToLogin": "Voltar ao login",
"loading.tagline": "A preparar os teus chats",
"login.welcome": "Bem-vindo de volta",
"login.subtitle": "Inicia sessão no KisAssistant para continuar",
"login.usernamePh": "Nome de utilizador",
"login.keyPh": "Chave de acesso",
"login.failed": "Falha no login",
"login.unlock": "Desbloquear",
"login.newHere": "Novo por aqui?",
"login.register": "Registar",
"login.regTipOn": "Criar uma conta",
"login.regTipOff": "Registo desativado nesta plataforma",
"login.requestAccess": "Pedir acesso",
"login.forgot": "Esqueceste a chave?",
"login.perk1": "Privado por design — sem cookies nem rastreio",
"login.perk2": "Os teus modelos, em tempo real",
"login.adminNotePre": "A chave admin vive no .env do servidor",
"login.adminNotePost": "; as chaves são emitidas pelo admin.",
"login.totpIntro": "Dois fatores para @{user} — escreve o código de 6 dígitos da app.",
"login.totpAria": "Código do autenticador",
"login.totpInvalid": "Código inválido",
"login.verify": "Verificar",
"sidebar.newChat": "Novo chat",
"sidebar.collapse": "Ocultar barra lateral",
"sidebar.closeDrawer": "Fechar chats",
"sidebar.searchPh": "Pesquisar chats…",
"sidebar.searchAria": "Pesquisar conversas",
"sidebar.clearSearch": "Limpar pesquisa",
"sidebar.searching": "A pesquisar…",
"sidebar.noMatch": "Sem resultados para «{q}».",
"sidebar.youPrefix": "tu: ",
"sidebar.emptyA": "Ainda sem conversas.",
"sidebar.emptyB": "Começa um novo chat acima.",
"sidebar.rename": "Renomear",
"sidebar.topic": "Definir tópico",
"sidebar.share": "Partilhar publicamente",
"sidebar.delete": "Eliminar",
"sidebar.convOptions": "Opções da conversa",
"sidebar.admin": "admin",
"sidebar.adminCenter": "Centro admin",
"sidebar.adminCenterTip": "Abrir o Centro admin",
"sidebar.settingsTip": "Perfil e definições",
"sidebar.logout": "Sair",
"sidebar.archive": "Arquivar",
"chat.expand": "Mostrar barra lateral",
"chat.openNav": "Abrir chats",
"chat.modelAria": "Modelo",
"chat.noModels": "Sem modelos",
"chat.selectModel": "Escolher modelo…",
"chat.personalTag": "chave pessoal",
"toast.chatDeleted": "Chat “{title}” eliminado",
"toast.chatArchived": "Chat “{title}” arquivado",
"toast.chatUnarchived": "Chat “{title}” desarquivado",
"toast.modelChanged": "Modelo: {label}",
"toast.themeChanged": "Tema alterado",
"toast.accentChanged": "Cor de destaque alterada",
"toast.unshared": "Link partilhado removido",
"toast.settingsSaved": "Definições guardadas",
"toast.convUpdated": "Conversa “{title}” atualizada",
"chat.you": "Tu",
"chat.greet": "Como posso ajudar, {name}?",
"chat.greetSub": "Escolhe um modelo e escreve abaixo. Markdown suportado.",
"chat.thinking": "A pensar…",
"chat.placeholder": "Escreve ao KisAssistant…",
"chat.send": "Enviar",
"chat.attachTip": "Anexar ficheiro",
"chat.removeAttach": "Remover {name}",
"chat.ocrOpt": "Transcrever imagem",
"chat.unavailable": "(indisponível)",
"chat.ocrHint": "JPG, PNG, WEBP — OCR no servidor, revês o texto antes",
"chat.textOpt": "Anexar ficheiro de texto",
"chat.textHint": "TXT ou Markdown, máx. 500KB",
"chat.attachNote":
"Uploads só via ferramentas da plataforma. Imagens chegam ao modelo como texto revisto — nunca brutas.",
"chat.wiki": "Wiki e docs",
"attach.tooBigImg": "Imagem muito grande (máx. 5MB).",
"attach.tooBigText": "Ficheiro muito grande (máx. 500KB).",
"attach.uploadFailed": "Falha no upload",
"attach.kindOcr": "transcrição de imagem",
"attach.kindText": "ficheiro de texto",
"attach.tpl": "[anexo {kind}: {name}]",
"attach.chatError": "**Erro:** o modelo não respondeu. Tenta de novo.",
"dlg.editConv": "Editar conversa",
"dlg.fTitle": "Título",
"dlg.fTopic": "Tópico",
"dlg.topicHint": "Etiqueta curta, ex. cozinha, rust, viagens.",
"dlg.noTopic": "Sem tópico",
"dlg.recoverTitle": "Recuperar chave",
"dlg.recoverIntro":
"Escreve o teu username. Receberás um link que emite uma chave nova (a antiga deixa de funcionar).",
"dlg.sendLink": "Enviar link",
"dlg.reqFailed": "Pedido falhou",
"dlg.recoverSent":
"Se @{user} existe com email de recuperação, um link vai a caminho{fromPart} (válido 60 minutos, uso único).",
"dlg.recoverSentFrom": " de {from}",
"dlg.spamNote": "Vê o inbox — e o spam, pode ter caído lá.",
"dlg.noMailNote":
"Nada chega? Então não há email definido e não é possível — contacta o admin do site.",
"dlg.registerTitle": "Criar uma conta",
"dlg.regWelcome":
"Bem-vindo, @{user}! A tua chave — copia agora, não será mostrada de novo.",
"dlg.regContinue": "Copiar e ir ao login",
"dlg.regFailed": "Registo falhou",
"dlg.emailOpt": "Email (opcional, para recuperar a chave)",
"dlg.shareTitle": "Partilhar publicamente",
"dlg.shareCreating": "A criar link público…",
"dlg.shareIntro": "Quem tiver este link pode ler {title}. Sem login.",
"dlg.unshare": "Remover partilha",
"dlg.reviewOcr": "Rever transcrição",
"dlg.reviewText": "Rever anexo",
"dlg.transcribing": "A transcrever imagem no servidor (OCR)…",
"dlg.uploadingTools": "Upload via ferramentas…",
"dlg.ocrExpl":
"A imagem foi transcrita em texto no servidor — o modelo recebe este texto, nunca a imagem. Corrige abaixo e anexa.",
"dlg.textExpl":
"O ficheiro foi enviado via ferramentas. O texto será anexado à mensagem. Edita e anexa.",
"dlg.truncWarn": "Transcrição cortada no limite — falta o fim.",
"dlg.attachBtn": "Anexar à mensagem",
"dlg.chars": "{n} caracteres",
"settings.title": "Definições",
"settings.searchPh": "Pesquisar definições…",
"settings.searchAria": "Pesquisar definições",
"settings.clearSearch": "Limpar pesquisa",
"settings.noMatch": "Sem definições para «{q}».",
"settings.profile": "Perfil",
"settings.appearance": "Aparência",
"settings.features": "Funções",
"settings.avatarUpload": "Enviar avatar",
"settings.dropIdle": "Larga uma imagem ou clica para enviar",
"settings.dropActive": "Larga!",
"settings.uploading": "A enviar…",
"settings.avatarHint": "jpg · png · webp — máx. 5MB — 5 mudanças por 2h",
"settings.username": "Nome de utilizador",
"settings.usernameHint":
"Nome de acesso. 2–32 caracteres: minúsculas, dígitos, . _ -. Efeito imediato.",
"settings.email": "Email de recuperação",
"settings.emailHint": "Opcional. Só para te enviar uma chave nova.",
"settings.accent": "Cor de destaque",
"settings.accentHint": "Aplicada na hora, guardada neste dispositivo.",
"settings.customColor": "Cor custom",
"settings.customAria": "Cor de destaque personalizada",
"settings.accentAria": "Destaque: {label}",
"settings.featHint": "Liga funções do editor. Na hora, neste dispositivo.",
"settings.providers": "Provedores",
"providers.intro":
"Ligue as suas chaves API. Os modelos dos provedores ligados aparecem no menu de modelos em cima.",
"providers.hint":
"As chaves ficam neste servidor e nunca mais são mostradas — só os últimos 4 caracteres. O uso é cobrado na sua conta e a política de modelos do admin continua válida.",
"providers.connected": "Ligado",
"providers.notConnected": "Desligado",
"providers.keyPh": "Cole a chave API…",
"providers.saveKey": "Guardar",
"providers.removeKey": "Remover",
"providers.replaceKey": "Substituir",
"providers.getKey": "Obter chave",
"providers.keySaved": "Chave guardada — os modelos já estão no menu.",
"providers.keyRemoved": "Chave removida.",
"providers.invalidKey": "Essa chave parece inválida (8–256 caracteres, sem espaços).",
"providers.loadFailed": "Não foi possível carregar os provedores.",
"accent.preset.emerald": "Esmeralda",
"accent.preset.rose": "Rosa",
"accent.preset.blue": "Azul",
"accent.preset.violet": "Violeta",
"accent.preset.amber": "Amarelo",
"accent.preset.orange": "Laranja",
"accent.preset.teal": "Turquesa",
"accent.preset.pink": "Rosa choque",
"feat.thinking.label": "Raciocínio",
"feat.thinking.hint": "Pede ao modelo para raciocinar passo a passo.",
"feat.attachments.label": "Anexos",
"feat.attachments.hint": "Anexa imagens (transcrição OCR) e textos.",
"feat.deepSearch.label": "Pesquisa profunda",
"feat.deepSearch.hint": "Pesquisa fontes frescas na web. Em breve.",
"feat.soon": "(breve)",
"admin.title": "Contas",
"admin.intro":
"Contas sem KYC: crias um nome, entregas a chave uma vez. Hash guardado — regenera para rodar.",
"admin.keyOnce": "Chave para @{user} — mostrada uma vez, copia agora:",
"admin.newAccount": "Nova conta",
"admin.email": "Email (recuperação)",
"admin.createFailed": "Falha ao criar",
"admin.regenFailed": "Falha ao regenerar",
"admin.deleteFailed": "Falha ao eliminar",
"admin.loadFailed": "Falha ao carregar",
"admin.searchPh": "Pesquisar contas…",
"admin.searchAria": "Pesquisar contas",
"admin.sortAria": "Ordenar contas",
"admin.filterAria": "Filtrar contas",
"admin.sortNewest": "Mais novas",
"admin.sortOldest": "Mais antigas",
"admin.sortAz": "A → Z",
"admin.sortZa": "Z → A",
"admin.filterAll": "Todas as contas",
"admin.filterWith": "Com email",
"admin.filterNo": "Sem email",
"admin.countMany": "{total} contas · página {page} de {pages}",
"admin.countOne": "{total} conta · página {page} de {pages}",
"admin.noEmail": "sem email",
"admin.editProfile": "Editar perfil",
"admin.regenKey": "Regenerar chave (revoga sessões)",
"admin.deleteAccount": "Eliminar conta",
"admin.deleteTitle": "Eliminar @{user}?",
"admin.deleteMsg": "Remove para sempre conta, conversas e partilhas.",
"admin.prevPage": "Página anterior",
"admin.nextPage": "Página seguinte",
"ollama.models": "Modelos Ollama",
"ollama.desc": "Saca modelos para o host Ollama ou remove locais. Só admin.",
"ollama.pulling": "A sacar {name}",
"ollama.customTag": "Tag custom",
"ollama.customHint": "ex. llama3.2:3b, ou nome da biblioteca",
"ollama.pull": "Sacar",
"ollama.installed": "Instalados ({n})",
"ollama.noneYet": "Sem modelos locais ainda.",
"ollama.catalog": "Catálogo",
"ollama.delTitle": "Eliminar {name}?",
"ollama.delMsg": "O modelo sai do host. Saca de novo quando quiseres.",
"ollama.contacting": "A contactar Ollama…",
"ollama.pullingSt": "A sacar…",
"ollama.doneSt": "Pronto",
"ollama.pullFailed": "Falha no download",
"ollama.delTip": "Eliminar {name}",
"ollama.sizeAria": "tamanho de {name}",
"ollama.cat.llama3_2": "Compacto Meta para o dia a dia",
"ollama.cat.llama3_1": "O workhorse da Meta",
"ollama.cat.qwen2_5": "Multilingue Alibaba versátil",
"ollama.cat.gemma2": "Aberto e eficiente do Google",
"ollama.cat.mistral": "Mistral 7B — rápido e capaz",
"ollama.cat.phi3": "Pequeno modelo Microsoft",
"ollama.cat.deepseek_r1": "Modelo de raciocínio (cadeia de pensamento)",
"ollama.cat.codellama": "Código e chat de código",
"ollama.cat.llava": "Visão (percebe imagens)",
"ollama.cat.nomic_embed_text": "Embeddings de texto",
"center.title": "Centro admin",
"center.back": "Voltar ao chat",
"center.tabAccounts": "Contas",
"center.tabFeatures": "Funções",
"center.tabMail": "Mail",
"center.tabModels": "Modelos",
"models.title": "Modelos",
"models.desc": "Ative ou limite cada modelo. Os desativados somem do seletor; os limites valem por utilizador (admins isentos).",
"models.refresh": "Atualizar",
"models.refreshAria": "Atualizar modelos",
"models.enabled": "Ativo",
"models.hourly": "por hora",
"models.daily": "por dia",
"models.unlimited": "Ilimitado",
"models.ollamaTitle": "Biblioteca Ollama",
"models.ollamaDesc": "Baixar ou remover modelos locais.",
"models.empty": "Nenhum modelo disponível.",
"models.saveFailed": "Falha ao guardar",
"models.connTitle": "Conectividade Ollama",
"models.connDesc": "Estado ao vivo do servidor Ollama: alcance, versão, latência e modelos instalados.",
"models.connOnline": "Online",
"models.connOffline": "Offline",
"models.connDisabledState": "Desativado",
"models.connCheck": "Verificar agora",
"models.connCheckAria": "Verificar a conectividade Ollama agora",
"models.connHost": "Servidor",
"models.connVersion": "Versão",
"models.connLatency": "Latência",
"models.connModels": "Modelos",
"models.connEmpty": "Nenhum modelo no servidor Ollama — baixe um da biblioteca abaixo.",
"models.connHint": "Certifique-se de que o Ollama está a correr e de que OLLAMA_HOST aponta para ele.",
"center.locked": "Só admins",
"center.lockedSub": "Entra como admin para abrir o Centro.",
"center.regTitle": "Registo público",
"center.regDesc": "Mostra Registar no login. Off = só contas do admin. Ligar aposenta a lista abaixo.",
"center.accTitle": "Pedidos de acesso (lista)",
"center.accDescOn": "Indisponível com registo público — substitui.",
"center.accDescOff": "Mostra Pedir acesso no login. Triagem na aba Acesso.",
"center.ocrTitle": "Ferramenta OCR",
"center.ocrDesc": "Transcrição no servidor. Precisa tesseract.",
"center.reportsTitle": "Denúncias de mensagens",
"center.reportsDesc":
"Bandeira sob as respostas. Off = bandeira cinzenta com aviso e novas denúncias recusadas.",
"center.usernameChangeTitle": "Mudanças de nome",
"center.usernameChangeDesc":
"Permite renomear-se em Definições → Perfil. Off = campo bloqueado (o admin continua a poder renomear).",
"settings.usernameDisabled": "Mudanças de nome desativadas pelo administrador.",
"center.mailTitle": "Emails de recuperação",
"center.mailChecking": "A verificar…",
"center.mailFrom": "Ativo — enviados de {from}",
"center.mailDefault": "Ativo — enviados do remetente",
"center.mailOff": "Desligado — define SMTP_HOST",
"center.mailNote":
"Credenciais SMTP vivem no servidor (ver docs/OPERATIONS.md), nunca aqui. Email define-se no perfil ou criação.",
"center.on": "Sim",
"center.off": "Não",
"share.fallback": "Chat partilhado",
"share.open": "Abrir KisAssistant",
"share.gone": "Este chat partilhado sumiu",
"share.goneSub": "Link inválido, expirado ou removido pelo autor.",
"share.back": "Voltar",
"share.loading": "A carregar chat…",
"share.by": "por {name}",
"reset.checking": "A verificar link…",
"reset.invalid": "Link inválido",
"reset.invalidSub":
"Link desconhecido, usado ou expirado. Pede outro no login.",
"reset.readyTitle": "Nova chave para @{user}?",
"reset.readySub": "Emite já uma chave nova. A antiga morre.",
"reset.issue": "Emitir nova chave",
"reset.issuing": "A emitir…",
"reset.doneTitle": "Nova chave pronta",
"reset.doneSub": "Copia agora — não será mostrada de novo. Entra com ela.",
"reset.goLogin": "Ir ao login",
"reset.failed": "Falha na recuperação",
"app.deleteConvTitle": "Eliminar conversa?",
"app.deleteConvMsg": "«{title}» e mensagens serão eliminados.",
"settings.language": "Idioma",
"settings.languageHint": "Idioma da interface. Na hora, neste dispositivo.",
"settings.security": "Segurança",
"sec.accessKey": "Chave de acesso",
"sec.accessKeyHint":
"Roda a tua chave. Sessões antigas morrem na hora — entras com a nova.",
"sec.rotate": "Rodar a minha chave",
"sec.rotateConfirm": "Clica de novo para confirmar",
"sec.rotationFailed": "Falha ao rodar",
"sec.totp": "Dois fatores (TOTP)",
"sec.totpChecking": "A verificar…",
"sec.totpAddHint":
"Adiciona um código de 6 dígitos da app além da chave.",
"sec.totpEnable": "Ativar dois fatores",
"sec.totpSecretHint":
"Adiciona este segredo à app (ou abre o link otpauth) e escreve um código:",
"sec.totpConfirm": "Confirmar",
"sec.totpDisableLabel": "Desligar com um código atual",
"sec.totpDisable": "Desligar 2FA",
"sec.setupFailed": "Falha ao configurar",
"sec.passkeys": "Passkeys",
"sec.passkeysHint":
"WebAuthn / autenticadores do sistema — precisa RP no servidor.",
"sec.danger": "Zona perigosa",
"sec.dangerHint":
"Elimina a conta com chats, partilhas e sessões. Sem volta.",
"sec.deleteMe": "Eliminar a minha conta",
"sec.deleteFailed": "Falha ao eliminar",
"sec.newKeyTitle": "Nova chave de acesso",
"sec.newKeyHint":
"Copia agora — não será mostrada de novo. Sessões antigas morrem.",
"sec.newKeyDone": "Pronto — sair",
"sec.deleteTitle": "Eliminar a tua conta?",
"sec.deleteMsg":
"Remove para sempre a conta com conversas, partilhas e sessões. Sem volta.",
"sec.deleteForever": "Eliminar para sempre",
"sec.avatarTooBig": "Ficheiro muito grande (máx. 5MB).",
"sec.avatarType": "Só imagens jpg, png ou webp.",
"center.tabAccess": "Acesso",
"center.smtpHost": "Servidor",
"center.smtpPort": "Porta",
"center.smtpUser": "Utilizador",
"center.smtpPass": "Palavra-passe",
"center.smtpFrom": "Remetente",
"center.smtpAppUrl": "URL da app",
"center.notSet": "(não definido)",
"center.noAuth": "(sem auth)",
"center.tlsImplicit": "TLS implícito (465)",
"center.tlsStarttls": "STARTTLS (587)",
"center.showPass": "Mostrar palavra-passe SMTP",
"center.hidePass": "Ocultar palavra-passe SMTP",
"center.hiddenPass": "palavra-passe oculta",
"center.mailTestTitle": "Teste de ligação",
"center.mailTestDesc":
"Verifica a ligação e envia um mail real para um endereço teu.",
"center.verifyConn": "Verificar ligação",
"center.verifying": "A verificar…",
"center.sendTest": "Enviar mail de teste",
"center.sendingMail": "A enviar…",
"center.testToAria": "Email de teste",
"center.connOk": "Ligação OK — SMTP acessível, auth aceite.",
"center.verifyFailed": "Verificação falhou",
"center.testSent": "Mail de teste enviado para {to}{tail}.",
"center.mailSendFailed": "Falha ao enviar",
"center.credsNote":
"Credenciais vivem no servidor (ver docs/OPERATIONS.md), só leitura aqui. Email define-se no perfil ou criação.",
"access.status.pending": "Pendente",
"access.status.reviewing": "Em revisão",
"access.status.accepted": "Aceite",
"access.status.refused": "Recusado",
"access.filter.all": "todos",
"access.filter.pending": "pendentes",
"access.filter.reviewing": "em revisão",
"access.filter.accepted": "aceites",
"access.filter.refused": "recusados",
"access.refresh": "Atualizar",
"access.refreshAria": "Atualizar pedidos",
"access.empty": "Sem pedidos. A lista está vazia.",
"access.emptyFiltered": "Nada com este estado.",
"access.msgOne": "1 mensagem",
"access.msgMany": "{n} mensagens",
"access.accountCreated": "Conta criada — chave única, copia agora:",
"access.replyPh": "Responder (chega por email)…",
"access.replyAria": "Responder ao requerente",
"access.reasonLabel": "Motivo (enviado com a decisão)",
"access.reasonPh": "Motivo opcional…",
"access.btnReviewing": "Em revisão",
"access.btnAccept": "Aceitar",
"access.btnRefuse": "Recusar",
"access.closedNote": "Ticket fechado ({status}).",
"access.reasonWord": "Motivo",
"access.youAdmin": "Tu (admin)",
"access.sendFailed": "Falha ao enviar",
"access.updateFailed": "Falha ao atualizar",
"live.newRequest": "New access request from @{user}",
"live.newMessage": "New message from @{user}",
"live.newReport": "New content report ({reason})",
"live.adminReply": "Admin replied to your ticket",
"live.ticketStatus": "Ticket {status}",
"msg.copy": "Copiar mensagem",
"msg.search": "Pesquisar na web",
"msg.report": "Denunciar resposta",
"msg.reportDisabled": "Denúncias desativadas",
"msg.retry": "Tentar novamente",
"report.title": "Denunciar esta resposta",
"report.reason": "Motivo",
"report.reasonPh": "Selecione um motivo…",
"report.reason.copyright": "Direitos autorais",
"report.reason.gore": "Gore / CSAM / NSFW",
"report.reason.falseinfo": "Informação falsa",
"report.reason.bug": "Bug",
"report.details": "Detalhes (opcional)",
"report.detailsPh": "O que há de errado nesta resposta? (opcional)",
"report.submit": "Enviar denúncia",
"report.sent": "Denúncia enviada — um administrador irá analisá-la.",
"report.failed": "Não foi possível enviar a denúncia",
"center.tabReports": "Denúncias",
"reports.filter.all": "todas",
"reports.filter.open": "abertas",
"reports.filter.reviewing": "em análise",
"reports.filter.resolved": "resolvidas",
"reports.filter.dismissed": "rejeitadas",
"reports.status.open": "Aberta",
"reports.status.reviewing": "Em análise",
"reports.status.resolved": "Resolvida",
"reports.status.dismissed": "Rejeitada",
"reports.refresh": "Atualizar",
"reports.refreshAria": "Atualizar denúncias",
"reports.empty": "Nenhuma denúncia de conteúdo ainda.",
"reports.emptyFiltered": "Nada com este estado.",
"reports.response": "Resposta denunciada",
"reports.noContent": "Nenhum conteúdo capturado.",
"reports.model": "Modelo",
"reports.reporter": "Autor",
"reports.conversation": "Conversa",
"reports.detailsGiven": "Detalhes do autor",
"reports.noteLabel": "Nota do admin",
"reports.notePh": "Nota interna…",
"reports.noteWord": "Nota",
"reports.btnReviewing": "Em análise",
"reports.btnResolve": "Resolver",
"reports.btnDismiss": "Rejeitar",
"reports.updateFailed": "Falha ao atualizar",
"reports.closedNote": "Denúncia {status}.",
"report.alreadyReported": "Esta resposta já foi denunciada.",
"reports.prompt": "Pergunta do utilizador",
"reports.unreliable": "Autor pouco fiável",
"reports.shadowban": "Silenciar autor",
"reports.unshadowban": "Tirar silêncio",
"reports.shadowbanTitle": "Silenciar este autor?",
"reports.shadowbanMsg": "As denúncias de @{user} continuarão a ser aceites, mas marcadas como pouco fiáveis e excluídas da contagem.",
"reports.unshadowbanTitle": "Tirar o silêncio?",
"reports.unshadowbanMsg": "As denúncias de @{user} voltarão a contar.",
"review.title": "Pedido de acesso",
"review.loadingTicket": "A carregar ticket…",
"review.notFound": "Ticket não encontrado",
"review.notFoundSub":
"Link desconhecido. Vê o URL do teu email ou pede acesso no login.",
"review.adminNote": "Nota do admin:",
"review.acceptedHint":
"Conta criada — vê o email com a chave e entra.",
"review.closedHint":
"Ticket fechado. Emails não são lidos — se preciso, pede de novo.",
"review.replyPh": "Defende o teu caso…",
"review.replyAria": "Responder ao teu ticket",
"review.mailHint":
"Emails são de sentido único — responde aqui, não por email.",
"review.status.pending": "Pendente de revisão",
"review.status.reviewing": "Em revisão",
"review.status.accepted": "Aceite",
"review.status.refused": "Recusado",
"review.admin": "Admin",
"review.you": "Tu",
"review.requestTitle": "Pedir acesso",
"review.requestIntro":
"Reserva um nome e diz porque queres entrar. Um admin revê cada pedido — segues o fio no teu ticket e por email.",
"review.emailHint": "Obrigatório — avisos e respostas chegam aqui.",
"review.whyLabel": "Porque dar-te acesso?",
"review.whyHint": "10+ caracteres. Isto abre o teu ticket.",
"review.whyPh": "Quero…",
"review.emailLabel": "Email",
"review.sendRequest": "Enviar pedido",
"review.received": "Pedido recebido",
"review.reserved":
"@{user} fica reservado enquanto um admin revê. Um email com o teu ticket vai a caminho.",
"review.copyLink": "Copiar link",
"review.openTicket": "Abrir o meu ticket",
"admin.editUserTitle": "Editar @{user}",
"admin.avatarUrl": "URL do avatar",
"archived.readonly": "Este chat está arquivado e é só de leitura.",
"archived.unarchive": "Desarquivar",
"archived.title": "Conversas arquivadas",
"archived.empty": "Nenhuma conversa arquivada.",
"archived.view": "Ver",
"archived.deleteTitle": "Eliminar esta conversa arquivada?",
"archived.deleteMsg": "Isto remove permanentemente a conversa e todas as mensagens.",
};
const dicts: Record<LangId, Dict> = { en, es, fr, ru, it, pt };
const STORE_KEY = "kisassistant_lang";
function detectLang(): LangId {
try {
const saved = localStorage.getItem(STORE_KEY);
if (
saved === "en" ||
saved === "es" ||
saved === "fr" ||
saved === "ru" ||
saved === "it" ||
saved === "pt"
) {
return saved;
}
} catch {
// storage unavailable — fall through to browser detection
}
const nav = (navigator.language || "en").toLowerCase().split("-")[0];
if (
nav === "es" ||
nav === "fr" ||
nav === "ru" ||
nav === "it" ||
nav === "pt"
)
return nav;
return "en";
}
let current: LangId = detectLang();
if (typeof document !== "undefined") document.documentElement.lang = current;
const listeners = new Set<() => void>();
export function getLang(): LangId {
return current;
}
/** Persist the language (per browser) and re-render every subscriber. */
export function setLang(lang: LangId): void {
if (current === lang) return;
current = lang;
try {
localStorage.setItem(STORE_KEY, lang);
} catch {
// ignore
}
if (typeof document !== "undefined") document.documentElement.lang = lang;
listeners.forEach((fn) => fn());
}
/** Global translate function: t("login.welcome"), t("chat.greet", { name }). */
export function t(
key: StringKey,
vars?: Record<string, string | number>,
): string {
let s: string = dicts[current][key] ?? dicts.en[key] ?? key;
if (vars) {
for (const [k, v] of Object.entries(vars))
s = s.replaceAll(`{${k}}`, String(v));
}
return s;
}
/** Reactive hook — components using translated strings must call it so they re-render on language switch. */
export function useT(): { t: typeof t; lang: LangId } {
useSyncExternalStore(
(fn) => {
listeners.add(fn);
return () => {
listeners.delete(fn);
};
},
() => current,
);
return { t, lang: current };
}