{
  "channel": {
    "tab": "Channels",
    "chatTab": "Chat",
    "empty": "No channels yet ✿",
    "dmLabel": "Messages",
    "dmHint": "Primary Agent Only",
    "groupLabel": "Channels",
    "noMessages": "No messages yet",
    "nameExists": "This channel name already exists",
    "membersCount": " members",
    "info": "Channel info",
    "readOnly": "🔒 This is a private message between agents, view only",
    "inputPlaceholder": "Send a message...",
    "sendFailed": "Send failed",
    "createTitle": "New Channel",
    "createName": "Channel name",
    "createNamePlaceholder": "e.g. design-team",
    "createMembers": "Members",
    "createIntro": "Description",
    "createIntroPlaceholder": "Describe what this channel is for...",
    "createCancel": "Cancel",
    "createConfirm": "Create",
    "nameRequired": "Please enter a channel name",
    "minMembers": "Select at least 2 members",
    "created": "Channel #{name} created ✿",
    "createFailed": "Create failed",
    "alreadyExists": "Channel already exists",
    "deleteChannel": "Delete channel",
    "deleteConfirm": "Delete channel \"{name}\"? Message history cannot be recovered.",
    "deleted": "Channel deleted",
    "deleteFailed": "Delete failed",
    "warningTitle": "About Channels",
    "warningBody": "I believe letting assistants with different memories and thinking styles interact can spark more inspiration, so I built a place where agents can talk to each other, even when you're away.\n\nPlease note that channels are experimental and may cause:\n1. Higher token usage\n2. Unexpected responses\n3. Memory confusion\n\nUse with caution",
    "warningConfirm": "I understand, enable channels",
    "disabled": "Channels disabled",
    "toggleLabel": "Channel toggle",
    "members": "Members",
    "createIntroOptional": "Description"
  },
  "sidebar": {
    "title": "Chats",
    "newChat": "New Chat",
    "collapse": "Collapse sidebar",
    "expand": "Expand chat list",
    "empty": "No chats yet ✿",
    "activity": "Activity",
    "jian": "Desk",
    "bridge": "Social Platforms",
    "toggle": "Sidebar",
    "bridgeShort": "Bridge"
  },
  "session": {
    "untitled": "New Chat",
    "messageCount": "{n} messages",
    "switchFailed": "Failed to switch session",
    "createFailed": "Failed to create session",
    "archiveFailed": "Failed to archive session"
  },
  "common": {
    "on": "On",
    "off": "Off",
    "copy": "Copy",
    "copied": "Copied",
    "copyText": "Copy text",
    "confirm": "Confirm",
    "cancel": "Cancel",
    "approve": "Approve",
    "reject": "Reject",
    "approved": "Approved",
    "rejected": "Rejected",
    "changeRejected": "{label} change cancelled",
    "changeTimeout": "{label} confirmation timed out",
    "noChats": "No chats",
    "noFiles": "No files",
    "executing": "Executing...",
    "user": "User",
    "me": "Me",
    "more": "More",
    "empty": "Empty",
    "edit": "Edit"
  },
  "chat": {
    "send": "Send",
    "steer": "Steer",
    "stop": "Stop",
    "browserScreenshot": "Browser screenshot",
    "compacting": "Compacting context"
  },
  "time": {
    "justNow": "Just now",
    "minutesAgo": "{n}m ago",
    "hoursAgo": "{n}h ago",
    "daysAgo": "{n}d ago",
    "dateFormat": "{m}/{d}",
    "today": "Today",
    "yesterday": "Yesterday",
    "thisWeek": "This Week",
    "earlier": "Earlier"
  },
  "status": {
    "connecting": "Connecting...",
    "connected": "Connected",
    "disconnected": "Disconnected",
    "serverNotReady": "Server not ready",
    "loading": "Loading...",
    "reconnecting": "Reconnecting",
    "reconnect": "Reconnect"
  },
  "input": {
    "placeholder": "Say something...",
    "selectFolder": "Select folder",
    "workspace": "Workspace: ",
    "selectWorkspace": "Select workspace",
    "planMode": "Use computer",
    "deskContext": "With desk context",
    "pastedImage": "Pasted image",
    "docContext": "With document",
    "thinkingLevel": {
      "off": "off",
      "auto": "auto",
      "high": "high",
      "xhigh": "max"
    },
    "thinkingDesc": {
      "off": "no reasoning",
      "auto": "model decides depth",
      "high": "deep reasoning",
      "xhigh": "full reasoning"
    },
    "contextWindow": "Context {windowK}k",
    "tokensUsed": "Used {tokensK}k ({pct}%)"
  },
  "slash": {
    "diary": "Write today's diary",
    "diaryBusy": "Writing diary...",
    "diaryDone": "Diary saved to diary folder",
    "diaryFailed": "Failed to write diary",
    "xing": "Reflect on this conversation",
    "compact": "Compact context",
    "compactBusy": "Compacting..."
  },
  "welcome": {
    "messages": [
      "What do you need? Leave it to {name}",
      "What's on your mind today?",
      "{name} is always here",
      "Need a hand with anything?",
      "Just say whatever comes to mind."
    ],
    "memoryOn": "Memory",
    "memoryOff": "Memory not used for this chat",
    "agentSelector": "Choose agent"
  },
  "drop": {
    "hint": "Drop to send files to {name}"
  },
  "attach": {
    "folder": "Folder",
    "copy": "Copy",
    "copied": "Copied ✓"
  },
  "cron": {
    "typeAt": "Once",
    "typeEvery": "Interval",
    "typeCron": "Scheduled",
    "confirm": {
      "approve": "Confirm",
      "reject": "Cancel",
      "created": "✓ Created",
      "rejected": "Cancelled"
    },
    "everyHours": "Every {n} hours",
    "everyMinutes": "Every {n} minutes",
    "hourly": "Hourly",
    "dailyAt": "Daily at {hour}:{min}",
    "weeklyAt": "{days} {hour}:{min}",
    "dayNames": [
      "Sun",
      "Mon",
      "Tue",
      "Wed",
      "Thu",
      "Fri",
      "Sat"
    ],
    "weekPrefix": ""
  },
  "mood": {
    "label": "✿ MOOD"
  },
  "xing": {
    "title": "Reflection",
    "thinking": "{name} is thinking"
  },
  "yuan": {
    "types": {
      "hanako": {
        "label": "Balanced assistant",
        "avatar": "Hanako.png"
      },
      "butter": {
        "label": "More expressive",
        "avatar": "Butter.png"
      },
      "ming": {
        "label": "More dependable",
        "avatar": "Ming.png"
      },
      "kong": {
        "label": "Vanilla",
        "avatar": "Kong.png"
      }
    },
    "title": "Yuan",
    "splash": {
      "butter": [
        "{name} flipped to a page left unfinished yesterday",
        "Some words haven't been said yet, {name} remembers",
        "{name} is napping",
        "They're piecing together memories too precious to forget",
        "{name} carefully tucked away your last mood",
        "A sentence has been sitting on the tip of the tongue for a while",
        "When they woke up, they first wondered what you were doing",
        "There are unfinished stories hidden in those ellipses",
        "{name} is folding what they want to say into tiny tiny notes",
        "Today's clouds look just like the photo you took that day"
      ],
      "ming": [
        "{name} drew a reference line in the margin of the draft paper",
        "Old questions are settling, new ideas are emerging",
        "They reviewed yesterday's clues once more",
        "{name} thinks the derivation of that formula was beautiful",
        "Some answers take time",
        "{name} is thinking about how to optimize work",
        "{name} is trying to keep everything in order",
        "They verified last time's conclusion again",
        "{name} thinks your reasoning that day was sharp",
        "{name} organized their thoughts while waiting for the coffee to cool"
      ]
    },
    "welcome": {
      "butter": [
        "Hey there~",
        "You came to find me?",
        "How's your day going?",
        "{name} has been here waiting for you",
        "{name} was just thinking of saying something to you"
      ],
      "ming": [
        "Hello. Whenever you're ready.",
        "{name} is ready",
        "What needs handling?",
        "Go ahead, {name} is listening"
      ]
    },
    "placeholder": {
      "butter": "Say whatever's on your mind...",
      "ming": "Go ahead..."
    }
  },
  "thinking": {
    "phrases": [
      "Thinking",
      "Mumbling to themselves",
      "Choosing their words",
      "Gears turning",
      "Gathering thoughts",
      "Brewing inspiration",
      "Digging through memories",
      "Something came to mind",
      "Bubbling with ideas",
      "Digesting what you said",
      "Drafting in their head",
      "Weaving their thoughts"
    ],
    "butter": [
      "Gently sorting through what you said",
      "Slowly unfolding your feelings",
      "Looking for the softest way to say it",
      "Words are lining up inside",
      "Folding their thoughts neatly",
      "Quietly reflecting",
      "Searching through memories for something",
      "Crafting a hug-sized reply",
      "Some feelings need time to untangle",
      "Making a soft space for your words"
    ],
    "ming": [
      "Analyzing",
      "Running scenarios",
      "Fact-checking",
      "Organizing thoughts",
      "Tracing the logic",
      "Outlining in their head",
      "Retrieving relevant info",
      "Verifying",
      "Breaking down the problem",
      "Synthesizing"
    ],
    "done": "Thinking complete",
    "active": "Thinking"
  },
  "toolGroup": {
    "success": "✿ {name} all done, piece of cake ~ · {n} steps",
    "failed": "⚠ Something seems off · {n} steps",
    "countWithFail": "{total} tools ({fail} failed)",
    "count": "{n} tools",
    "running": "{n} tools running"
  },
  "tool": {
    "web_search": {
      "running": "🌐 {name} is surfing the web",
      "done": "🌐 {name} is back from surfing",
      "failed": "🌐 {name} couldn't catch a wave"
    },
    "web_fetch": {
      "running": "📄 {name} is reading a webpage",
      "done": "📄 {name} finished reading",
      "failed": "📄 {name} couldn't fetch the page"
    },
    "search_memory": {
      "running": "💭 {name} is trying to remember",
      "done": "💭 {name} recalled something",
      "failed": "💭 {name} couldn't recall"
    },
    "bash": {
      "running": "💻 {name} is tiptoeing through your computer",
      "done": "💻 {name} is done with the computer",
      "failed": "💻 {name} command failed"
    },
    "read": {
      "running": "📖 {name} is reading a file",
      "done": "📖 {name} finished reading",
      "failed": "📖 {name} couldn't read"
    },
    "write": {
      "running": "✏️ {name} is putting pen to paper",
      "done": "✏️ {name} finished writing",
      "failed": "✏️ {name} couldn't write"
    },
    "edit": {
      "running": "✏️ {name} is putting pen to paper",
      "done": "✏️ {name} done editing",
      "failed": "✏️ {name} couldn't edit"
    },
    "edit-diff": {
      "running": "✏️ {name} is putting pen to paper",
      "done": "✏️ {name} done editing",
      "failed": "✏️ {name} couldn't edit"
    },
    "glob": {
      "running": "🔍 {name} is looking for files",
      "done": "🔍 {name} found them",
      "failed": "🔍 {name} couldn't find"
    },
    "grep": {
      "running": "🔍 {name} is searching through files",
      "done": "🔍 {name} search done",
      "failed": "🔍 {name} couldn't find"
    },
    "find": {
      "running": "🔍 {name} is looking for files",
      "done": "🔍 {name} found them",
      "failed": "🔍 {name} couldn't find"
    },
    "ls": {
      "running": "📂 {name} is peeking into a folder",
      "done": "📂 {name} done peeking",
      "failed": "📂 {name} couldn't peek"
    },
    "truncate": {
      "running": "✂️ {name} is tidying up a file",
      "done": "✂️ {name} all tidy",
      "failed": "✂️ {name} couldn't tidy"
    },
    "present_files": {
      "running": "📎 {name} is preparing the file",
      "done": "📎 File ready",
      "failed": "📎 Failed to present file"
    },
    "browser": {
      "running": "🌐 {name} is browsing the web",
      "done": "🌐 {name} done browsing",
      "failed": "🌐 {name} browser action failed"
    },
    "_fallback": {
      "running": "🔧 {name} is busy working…",
      "done": "🔧 {name} all done",
      "failed": "🔧 {name} something went wrong"
    }
  },
  "file_output": {
    "open": "Open",
    "copied": "Path copied"
  },
  "model": {
    "unknown": "Unknown model",
    "offline": "Offline",
    "switchFailed": "Failed to switch model"
  },
  "splash": {
    "lines": [
      "{name} remembers the evening light",
      "Some words sprouted in their memory",
      "They found your silhouette in memories",
      "Wind drifted through old conversations",
      "Those words soaked in time, turning soft",
      "{name} remembers you laughing that day",
      "A memory was dog-eared by you",
      "They gathered the scattered feelings",
      "{name} smelled oranges from an afternoon",
      "Those conversations still carry warmth"
    ]
  },
  "settings": {
    "title": "Settings",
    "back": "Back",
    "save": "Save",
    "saved": "Saved ✿",
    "saveFailed": "Failed to save",
    "noChanges": "Nothing to save",
    "autoSaved": "Auto-saved ✿",
    "tabs": {
      "interface": "Interface",
      "agent": "Agent",
      "me": "Me",
      "providers": "Providers",
      "models": "Models",
      "memory": "Memory",
      "work": "Work",
      "skills": "Skills",
      "bridge": "Social",
      "about": "About"
    },
    "appearance": {
      "title": "Appearance",
      "theme": "Theme",
      "warmPaper": "Warm Paper",
      "warmPaperMode": "Light",
      "midnight": "Aoi Night",
      "midnightMode": "Dark",
      "highContrast": "Clean White",
      "highContrastMode": "High Contrast",
      "grassAroma": "Grass Aroma",
      "grassAromaMode": "Butter",
      "contemplation": "Contemplation",
      "contemplationMode": "Ming",
      "absolutely": "Absolutely",
      "absolutelyMode": "A bit familiar",
      "delve": "Delve",
      "delveMode": "Let's explore",
      "deepThink": "Deep Think",
      "deepThinkMode": "Little Whale",
      "auto": "Auto",
      "autoMode": "System",
      "serifFont": "Serif Font",
      "serifFontHint": "Use serif font for body text"
    },
    "locale": {
      "title": "Language & Region",
      "language": "Language",
      "languageHint": "Page will reload after switching",
      "timezone": "Timezone",
      "timezoneHint": "Used for memory timestamps, journal entries, etc."
    },
    "agent": {
      "title": "Agent",
      "changeAvatar": "Change",
      "removeAvatar": "Remove avatar",
      "avatarRemoved": "Restored default avatar",
      "agentNameHint": "What they go by",
      "identity": "Identity",
      "identityHint": "A short description of who this agent is and what they're good at. Other agents use this to know them",
      "ishiki": "Ishiki",
      "ishikiHint": "Defines the assistant's character, tone and behavior. Names are auto-injected",
      "publicIshiki": "Public Ishiki",
      "publicIshikiHint": "For privacy, the assistant cannot access memories, your personal info, or any files and tools on your computer when talking to visitors.\nYou can set the assistant's reply style and guidelines for visitor conversations here.",
      "chatModel": "Model",
      "chatModelHint": "The model used for conversations and tasks",
      "addAgent": "New Agent",
      "createTitle": "New Agent",
      "namePlaceholder": "Give them a name",
      "cancel": "Cancel",
      "confirm": "Create",
      "nameRequired": "Please enter a name",
      "created": "{name} created ✿",
      "createFailed": "Create failed",
      "switched": "Switched to {name} ✿",
      "switchFailed": "Switch failed",
      "deleteBtn": "Delete agent",
      "deleteTitle1": "Delete {name}?",
      "deleteDesc1": "This will permanently delete all config, memory and conversations. This cannot be undone.",
      "deleteNext": "Continue",
      "deleteTitle2": "Type \"{name}\" to confirm",
      "deletePlaceholder": "Type agent name",
      "deleteConfirm": "Delete permanently",
      "deleteCancel": "Cancel",
      "deleted": "{name} deleted",
      "deleteFailed": "Delete failed",
      "setActive": "Set as active",
      "lastAgent": "Must keep at least one agent",
      "yuan": "Yuan",
      "yuanHint": "\"Yuan\" is the agent's innate thinking style. Build your unique companion from this foundation."
    },
    "about": {
      "title": "About Them",
      "tagline": "An assistant that lives in your computer, with a good memory.",
      "license": "License",
      "copyright": "Copyright",
      "licenseToggle": "License full text",
      "permissions": "Permissions",
      "fullAccess": "Full Access Mode",
      "fullAccessDesc": "Disable sandbox isolation and command restrictions. The agent gets full filesystem and terminal access (takes effect on new sessions)",
      "fullAccessWarningTitle": "About Full Access Mode",
      "fullAccessWarningBody1": "Once enabled, the agent will have full system privileges, including:",
      "fullAccessWarningBody2": "1. Filesystem is not sandboxed — can read/write any path\n2. Terminal commands are unrestricted — can run sudo, chmod, etc.\n3. OS-level isolation (macOS Seatbelt / Linux bubblewrap) will be disabled",
      "fullAccessWarningBody3": "Only recommended when you fully trust the agent's behavior and need system-level operations.",
      "fullAccessCancel": "Cancel",
      "fullAccessConfirm": "I understand the risks, enable",
      "updateAvailable": "New version available: v{{version}}",
      "updateDownload": "Download",
      "updateChecking": "Checking for updates…",
      "updateDownloading": "Downloading v{{version}}…",
      "updateReadyInstall": "v{{version}} ready to install",
      "updateInstall": "Install now",
      "updateProgress": "{{percent}}%",
      "updateError": "Update check failed",
      "updateLatest": "You're up to date",
      "updateCheckBtn": "Check for updates",
      "betaUpdates": "Receive beta updates"
    },
    "me": {
      "title": "Me",
      "changeAvatar": "Change",
      "userNameHint": "How they address you",
      "userProfile": "User Profile",
      "userProfileHint": "Help the assistant know you: interests, habits, preferences. Injected into the system prompt"
    },
    "crop": {
      "title": "Adjust avatar",
      "hint": "Drag to move, scroll to zoom",
      "cancel": "Cancel",
      "confirm": "Confirm",
      "updated": "Avatar updated ✿",
      "reset": "Avatar reset to default"
    },
    "providers": {
      "title": "Registered Providers",
      "addTitle": "Add Provider",
      "name": "Provider",
      "customName": "Name",
      "customUrl": "Base URL",
      "apiFormat": "API Protocol",
      "url": "Base URL",
      "apiKey": "API Key",
      "addBtn": "Add",
      "empty": "No providers registered yet",
      "fetchModels": "Fetch Models",
      "delete": "Delete provider",
      "modelCount": "{n} models",
      "fetchSuccess": "Fetched {n} models from {name}",
      "fetchFailed": "Fetch failed",
      "nameRequired": "Provider name is required",
      "urlRequired": "Base URL is required",
      "apiRequired": "API protocol is required",
      "added": "Added {name}",
      "deleted": "Deleted {name}",
      "noModels": "No models yet",
      "resetModels": "Reset Models",
      "apiType": "API Type",
      "verify": "Verify",
      "verifyConnection": "Verify Connection",
      "verifySuccess": "Connection verified",
      "verifyFailed": "Verification failed",
      "setupHint": "Enter API Key to activate this provider",
      "selectHint": "Select a provider to view details",
      "addCustom": "Add Custom Provider",
      "noKey": "Not configured",
      "remove": "Remove",
      "deleteConfirm": "Delete provider {name}? Associated models and favorites will be removed."
    },
    "oauth": {
      "title": "Quick Login",
      "login": "Login",
      "logout": "Logout",
      "loggedIn": "Logged in",
      "codePlaceholder": "Paste authorization code",
      "submit": "Submit",
      "success": "Login successful",
      "loggedOut": "Logged out",
      "failed": "Login failed",
      "deviceHint": "Enter this code in the browser to authorize",
      "waiting": "Waiting for authorization…",
      "clickToCopy": "Click to copy",
      "codeCopied": "Code copied",
      "addModel": "Add Model",
      "customModelPlaceholder": "Enter model ID"
    },
    "api": {
      "title": "Models & API",
      "mainApi": "Main API",
      "provider": "Provider",
      "baseUrl": "Base URL",
      "baseUrlHint": "Enter the Base URL explicitly",
      "apiKey": "API Key",
      "apiKeyPlaceholder": "Enter a new key to update",
      "utilityApi": "Utility Model API",
      "utilityApiHint": "If configured separately, provider, Base URL, and API key must all be explicit",
      "showKey": "Show",
      "hideKey": "Hide",
      "selectModel": "Select model",
      "customModel": "Custom...",
      "mainModelSection": "Models",
      "mainModelHint": "These models will be available in the chat page",
      "addModel": "Add Model",
      "defaultModel": "Default",
      "removeModel": "Remove",
      "noModels": "No models added yet",
      "otherModelSection": "Other",
      "chatModel": "Primary model",
      "utilityModel": "Utility (small)",
      "utilityModelHint": "Titles, light classification, etc. A cheap small model is recommended",
      "utilityLargeModel": "Utility (large)",
      "utilityLargeModelHint": "Activity summaries, task breakdown, etc. Falls back to small utility if empty",
      "searchProvider": "Search Service",
      "searchProviderField": "Search engine",
      "searchApiKey": "Search API Key",
      "searchApiKeyHint": "Enter the API key for the selected search provider",
      "favorites": "Favorites",
      "searchModel": "Search models...",
      "noFavorites": "Click ☆ to favorite models",
      "customInput": "Custom...",
      "editModel": "Edit",
      "contextLength": "Context Length",
      "contextShort": "Context",
      "maxOutput": "Max Output",
      "outputLength": "Output Length",
      "modelName": "Model",
      "output": "out",
      "save": "Save",
      "cancel": "Cancel",
      "thinkingLevel": "Reasoning Effort",
      "thinkingLevelHint": "Controls reasoning depth, only affects models that support reasoning",
      "thinkingLevels": {
        "off": "Off",
        "low": "Low",
        "medium": "Medium",
        "high": "High",
        "auto": "Auto",
        "xhigh": "Max"
      },
      "addedModels": "Added models",
      "displayName": "Display name"
    },
    "memory": {
      "sectionTitle": "Memory",
      "title": "Memory System",
      "needsUtilityModel": "Configure a Utility model in Models tab first",
      "compiled": "Current Memory",
      "compiledHint": "What the assistant remembers about you — important and recent things",
      "compiledView": "View Current Memory",
      "compiledEmpty": "No compiled memories yet",
      "compiledClear": "Clear",
      "compiledCleared": "Compiled memory cleared",
      "allMemories": "All Memories",
      "tokenBudget": "Memory capacity",
      "tokenBudgetHint": "Target token budget for memory.md",
      "decayPerDay": "Decay coefficient",
      "decayPerDayHint": "Base λ for Gaussian decay",
      "hitBonus": "Hit bonus",
      "hitBonusHint": "Score added each time a memory is referenced",
      "baseImportance": "Base importance",
      "baseImportanceHint": "Default initial score for new memories",
      "forgetSpeed": "Forget speed",
      "forgetSpeedHint": "1.0 = normal, 2.0 = twice as fast",
      "compileThreshold": "Compile threshold",
      "compileThresholdHint": "Memories below this score are excluded",
      "timezone": "Timezone",
      "timezoneHint": "Used for memory timestamps",
      "actions": {
        "title": "Memory Management",
        "view": "View Memories",
        "clear": "Clear Memories",
        "more": "More",
        "export": "Export",
        "import": "Import",
        "clearConfirm": "Are you sure you want to clear all memories? This cannot be undone.",
        "cancel": "Cancel",
        "confirmClear": "Confirm Clear",
        "viewTitle": "All Memories",
        "clearSuccess": "Memories cleared",
        "exportSuccess": "Export successful",
        "importSuccess": "{count} memories imported",
        "importing": "Importing...",
        "empty": "No memories yet",
        "invalidFile": "Invalid memory file",
        "activeOnly": "Set this agent as active first"
      },
      "unknownDate": "Unknown date",
      "threshold": {
        "title": "Memory Waterline",
        "hint": "You decide how many memories are remembered. A little noise is fine — LLMs are good at filtering.",
        "stats": "{remembered} / {total} memories remembered"
      },
      "activeOnly": "Set this agent as active first"
    },
    "pins": {
      "title": "Pinned Memories",
      "hint": "Always injected into conversations, never decay",
      "empty": "No pinned memories yet",
      "delete": "Delete",
      "addPlaceholder": "Add a pinned memory..."
    },
    "experience": {
      "title": "Experience",
      "hint": "Lessons the agent has learned, organized by category. The agent checks relevant experience before starting work",
      "empty": "No experience yet",
      "edit": "Edit",
      "deleteCategory": "Delete category"
    },
    "search": {
      "verify": "Verify",
      "verifying": "Verifying...",
      "verified": "Verified & saved ✿",
      "verifyFailed": "Verification failed",
      "noProvider": "Please select a search engine first",
      "noKey": "Please enter an API Key first"
    },
    "work": {
      "title": "Patrol",
      "heartbeatEnabled": "Patrol mode",
      "heartbeatOn": "On",
      "heartbeatOff": "Off",
      "heartbeatInterval": "Patrol interval",
      "heartbeatUnit": "minutes",
      "heartbeatDesc": "How often the assistant auto-checks the workspace",
      "cronAutoApprove": "Auto-approve cron jobs",
      "cronAutoApproveOn": "On",
      "cronAutoApproveOff": "Off",
      "cronAutoApproveDesc": "Allow the assistant to create scheduled tasks without confirmation",
      "homeFolder": "Workspace",
      "homeFolderDesc": "Default working directory for new chats, patrol and cron tasks",
      "homeFolderPlaceholder": "Not set (choose manually each time)",
      "homeFolderClear": "Clear",
      "homeFolderBrowse": "Browse"
    },
    "toolCaps": {
      "title": "Self-learning Skills"
    },
    "skills": {
      "title": "Skills",
      "desc": "Enable or disable skills for this agent. When enabled, the agent will automatically recognize and use matching skills in conversations.",
      "user": "User Skills",
      "system": "System Skills",
      "add": "Add Skill",
      "delete": "Delete",
      "deleteConfirm": "Delete skill \"{name}\"?",
      "installSuccess": "Skill \"{name}\" installed",
      "installError": "Install failed",
      "enabled": "Enabled",
      "disabled": "Disabled",
      "noSkills": "No skills available",
      "learned": "Agent Learned",
      "noLearned": "Agent has not learned any skills yet",
      "noUser": "No custom skills",
      "copyToSkills": "Copy to your skills",
      "copied": "Copied ✓",
      "copyFailed": "Copy failed",
      "dropzone": "Drop a skill folder to install, or click to browse",
      "learnHint": "Try asking your assistant: find me some safe and useful skills from GitHub",
      "reloaded": "Skills reloaded",
      "reload": "Reload skills",
      "compatTitle": "Compatible Skills",
      "compatDesc": "Auto-discover skills installed by other AI tools",
      "compatNoSkills": "No external skills found",
      "compatAddPath": "Add directory",
      "compatRemove": "Remove",
      "compatAutoDiscovered": "Auto-discovered",
      "compatNotInstalled": "Not installed",
      "learnCreate": "Create / install skills",
      "learnCreateDesc": "Allow the Agent to write new skills or install them via tool calls",
      "fetchRemote": "Fetch skills from GitHub / ClawHub",
      "fetchRemoteDesc": "When enabled, the Agent will proactively search and install suitable skills for specialized tasks. Use with caution",
      "safetyReview": "Safety review before install",
      "safetyReviewDesc": "Use AI to detect prompt injection and other security risks before installing skills",
      "fetchWarning": {
        "title": "About fetching remote skills",
        "body1": "When enabled, the Agent will proactively search, download and install suitable skills from GitHub and ClawHub during specialized tasks.",
        "body2": "Although automatic safety review and star-count checks are performed before installation, the following risks remain:",
        "risk1": "Skill content is not manually reviewed and may contain harmful instructions",
        "risk2": "The Agent may install skills that don't match expectations",
        "risk3": "Malicious skills may attempt to manipulate Agent behavior",
        "confirm": "I understand the risks, enable"
      },
      "safetyWarning": {
        "title": "Disable safety review",
        "body1": "Safety review detects potentially malicious content before installing skills, including:",
        "risk1": "Prompt injection (unauthorized instructions)",
        "risk2": "Overly broad trigger conditions",
        "risk3": "Social engineering and privilege escalation attempts",
        "body2": "After disabling, all skills will be installed without review.",
        "confirm": "I understand the risks, disable review"
      }
    },
    "bridge": {
      "telegram": "Telegram",
      "telegramToken": "Bot Token",
      "telegramHint": "Get from @BotFather",
      "feishu": "Feishu",
      "feishuAppId": "App ID",
      "feishuAppSecret": "App Secret",
      "feishuHint": "Get from Feishu Open Platform",
      "qq": "QQ",
      "qqAppId": "App ID",
      "qqAppSecret": "App Secret",
      "qqHint": "Get from QQ Bot Open Platform (q.qq.com/qqbot)",
      "wechat": "WeChat",
      "wechatHint": "Connect via WeChat iLink protocol",
      "wechatScan": "Scan to Login",
      "wechatRescan": "Re-login",
      "wechatLoggedIn": "Logged in",
      "wechatNeedScan": "Please scan QR code first",
      "wechatScanning": "Scan the QR code with WeChat",
      "wechatScanned": "Scanned, please confirm on your phone",
      "wechatExpired": "QR code expired",
      "wechatLoginSuccess": "Login successful",
      "wechatLoginFailed": "Login failed",
      "wechatUnbind": "Unbind",
      "wechatUnbound": "WeChat unbound",
      "connected": "Connected",
      "disconnected": "Not connected",
      "error": "Connection failed",
      "test": "Test Connection",
      "testOk": "Connection successful",
      "testFail": "Test failed",
      "noToken": "Please enter Bot Token first",
      "noCredentials": "Please enter App ID and App Secret first",
      "readOnly": "Read-only mode",
      "readOnlyDesc": "Bridge bots can only read files, no writing or command execution",
      "howTo": "Setup Guide",
      "tutorialTitle": "Platform Setup Guide",
      "tutorialTgSteps": [
        "Search for <code>@BotFather</code> in Telegram and open the chat",
        "Send <code>/newbot</code> and follow the prompts to set a name and username",
        "BotFather will reply with a Bot Token (like <code>123456:ABC-DEF...</code>)",
        "Paste the Token into the input field above and turn on the switch",
        "Find your Bot in Telegram and send a message to test it"
      ],
      "ownerSelect": "Which account is you",
      "ownerWarning": "Warning: The selected account will have access to your computer, memory, and private information. Make sure the account belongs to you.",
      "ownerNone": "Send a message first to select",
      "ownerSaved": "Saved",
      "ownerConfirmTitle": "Set as Owner?",
      "ownerConfirmText": "The Owner has full Agent access, including memory, tools, and personality. Make sure this is your own account.",
      "ownerConfirmCancel": "Cancel",
      "ownerConfirmSave": "Confirm",
      "tutorialFsSteps": [
        "Go to <code>open.feishu.cn</code>, log in and open the Developer Console",
        "Click \"Create Enterprise Custom App\", fill in the app name and description",
        "On the \"Credentials & Basic Info\" page, copy the <code>App ID</code> and <code>App Secret</code>",
        "Find \"Add App Capabilities\" in the left menu, add \"Bot\" capability and give it a name",
        "Go to \"Permissions\", search and enable <code>im:message</code> (send and receive messages)",
        "Go to \"Events & Callbacks\" → \"Event Configuration\", change to \"Receive events via long connection\"",
        "Click \"Add Event\", add <code>im.message.receive_v1</code> (receive messages)",
        "Important: Go to \"Version Management\", create and publish a version first (long connection config requires a published app)",
        "Paste the App ID and App Secret into the input fields above and turn on the switch"
      ],
      "whatsappHint": "Coming soon"
    }
  },
  "onboarding": {
    "welcome": {
      "title": "Hi, I'm {name} ✿",
      "subtitle": "I'm your personal AI assistant.\nLet's do some quick setup to get started.",
      "next": "Get Started"
    },
    "name": {
      "title": "What should I call you?",
      "subtitle": "This makes our conversations more natural",
      "placeholder": "Enter your name",
      "back": "Back",
      "next": "Next"
    },
    "provider": {
      "title": "Choose an AI Provider",
      "subtitle": "I need an AI model provider to work.\nPick your provider and enter your API Key.",
      "custom": "Custom...",
      "customName": "Name",
      "customNamePlaceholder": "e.g. my-provider",
      "customUrl": "API URL",
      "customUrlPlaceholder": "e.g. https://api.example.com/v1",
      "keyLabel": "API Key",
      "keyPlaceholder": "Paste your API Key",
      "test": "Test Connection",
      "testing": "Connecting...",
      "testSuccess": "Connected ✿",
      "testFailed": "Connection failed",
      "back": "Back",
      "next": "Next"
    },
    "model": {
      "title": "Choose a Chat Model",
      "subtitle": "This is the main model I'll use. Pick a smart, capable one.",
      "loading": "Fetching models...",
      "searchPlaceholder": "Search models...",
      "empty": "No models found",
      "utility": "Utility Model",
      "utilityHint": "Summaries, fact extraction — pick a fast, cheap model",
      "utilityLarge": "Utility Large",
      "utilityLargeHint": "Memory compilation, deep analysis — pick a capable model",
      "back": "Back",
      "next": "Next"
    },
    "theme": {
      "title": "Pick a Theme",
      "subtitle": "You can always change it later in Settings",
      "back": "Back",
      "next": "Next"
    },
    "tutorial": {
      "title": "All Set ✿",
      "memory": {
        "title": "Memory",
        "desc": "I remember key points from your conversations. Older, less-referenced memories fade naturally, just like ours."
      },
      "skills": {
        "title": "Skills",
        "desc": "I can read/write files, run commands, and search the web. Manage more skills in Settings."
      },
      "workspace": {
        "title": "Workspace",
        "desc": "Set a folder as your workspace and I can help manage your projects and files."
      },
      "jian": {
        "title": "Jian",
        "desc": "Drop a jian.md in any folder with your instructions.\nI'll pick it up during patrol and execute automatically."
      },
      "finish": "Let's Go"
    }
  },
  "activity": {
    "title": "Activity",
    "empty": "No activity yet. Patrol runs and scheduled tasks will appear here.",
    "back": "Back",
    "heartbeat": "Routine patrol",
    "delegate": "Delegated task",
    "cron": "Scheduled task",
    "patrolDone": "Patrol completed",
    "cronDone": "Scheduled task completed",
    "error": "Execution error",
    "viewSession": "View session →",
    "duration": "Took {text}"
  },
  "automation": {
    "title": "Scheduled Tasks",
    "empty": "No scheduled tasks yet.\nThe assistant will create them when needed.",
    "defaultModel": "Default model",
    "edit": "Edit",
    "delete": "Delete"
  },
  "desk": {
    "title": "Desk",
    "skills": "Skills",
    "cwdSkills": "Project Skills",
    "cwdSkillsEmpty": "No project skills in this folder",
    "cwdSkillsHint": "Create a .agents/skills/ directory to get started",
    "cwdSkillsDesc": "Skills follow workspace",
    "cwdSkillsDrop": "Drop folder or .zip to install skills",
    "deleteSkill": "Delete Skill",
    "openInFinder": "Open Folder",
    "jianLabel": "Jian",
    "jianPlaceholder": "Write something to tell the assistant how to handle files in this folder...",
    "emptyTitle": "Desk is empty",
    "emptyHint": "The desk is the assistant's patrol workspace and the default directory for every chat.\nSet a folder in settings.",
    "goToSettings": "Go to Settings",
    "fileLabel": "file",
    "openWithDefault": "Open with default app",
    "newFolder": "New Folder",
    "ctx": {
      "open": "Open",
      "openInFinder": "Open Folder",
      "rename": "Rename",
      "copyPath": "Copy Path",
      "delete": "Delete",
      "deleteN": "Delete {n} items",
      "newMdFile": "New Markdown Document",
      "newFolder": "New Folder"
    },
    "sort": {
      "label": "Sort",
      "mtime": "Modified",
      "nameAsc": "Name A→Z",
      "nameDesc": "Name Z→A",
      "size": "File size",
      "type": "File type",
      "mtimeShort": "Time",
      "nameAscShort": "Name↑",
      "nameDescShort": "Name↓",
      "sizeShort": "Size",
      "typeShort": "Type"
    }
  },
  "window": {
    "minimize": "Minimize",
    "maximize": "Maximize",
    "close": "Close"
  },
  "browser": {
    "using": "Using browser",
    "close": "Close browser",
    "closeBtn": "Close",
    "back": "Back",
    "forward": "Forward",
    "reload": "Reload",
    "emergencyStop": "Emergency stop AI control",
    "backgroundHint": "Background browser running, click to view",
    "background": "Background browser"
  },
  "bridge": {
    "selectChat": "Select a conversation",
    "noSessions": "No conversations yet",
    "noMessages": "No messages yet",
    "empty": "No messages",
    "notConfigured": "{platform} not configured",
    "goToSettings": "Go to Settings",
    "resetContext": "Clear context",
    "resetContextTip": "Next message will start a new conversation"
  },
  "error": {
    "pathsRequired": "paths array is required",
    "tooManyFiles": "Too many files (max {max}, got {n})",
    "pathNotFound": "Path not found",
    "missingParam": "Missing {param} parameter",
    "invalidJson": "Request body must be a JSON object",
    "sessionNotFound": "Session file not found",
    "stillStreaming": "{name} is still responding, please wait",
    "agentNameEmpty": "Agent name cannot be empty",
    "agentIdInvalid": "Agent ID contains invalid characters",
    "agentAlreadyExists": "Agent \"{id}\" already exists",
    "agentSwitching": "Agent switch in progress, please wait",
    "agentNotFound": "Agent \"{id}\" not found or not initialized",
    "agentModelNotAvailable": "Model \"{model}\" configured for agent \"{id}\" is not available",
    "agentDeleteActive": "Cannot delete the currently active agent",
    "agentNotExists": "Agent \"{id}\" does not exist",
    "modelNoResponse": "Model returned no content. Please check API configuration and network connection.",
    "noActiveSession": "No active session",
    "compacting": "Compaction in progress",
    "waitForReply": "Please wait for the response to finish before compacting",
    "compactFailed": "Compaction failed: {msg}",
    "maxImages": "Maximum {max} images allowed",
    "unsupportedImageFormat": "Unsupported image format: {mime}",
    "imageTooLarge": "Single image must not exceed 20MB",
    "viewImage": "(view image)",
    "searchProviderNotConfigured": "Search provider not configured",
    "searchProviderMissingKey": "Search provider \"{provider}\" is missing API Key",
    "searchProviderUnknown": "Unknown search provider: {provider}",
    "searchFailed": "Search failed: {msg}",
    "searchEmptyQuery": "Please provide a search query.",
    "searchNoResults": "No relevant results found. (via {provider})",
    "searchResults": "Search results (via {provider}):\n\n{results}",
    "searchError": "Search error: {msg}",
    "fetchEmptyUrl": "Please provide a URL to fetch.",
    "fetchHttpOnly": "Only http/https URLs are supported.",
    "fetchInvalidUrl": "Invalid URL: {url}",
    "fetchSsrf": "Access to internal network address denied: {host}",
    "fetchRedirectLimit": "Redirect limit exceeded ({max})",
    "fetchHttpError": "Fetch failed: HTTP {status} {statusText}",
    "fetchTruncated": "\n\n[... content truncated, {len} characters total]",
    "fetchSource": "Source: {host}{path} ({format})\n\n",
    "fetchTimeout": "Fetch timeout ({sec}s): {url}",
    "fetchError": "Fetch error: {msg}",
    "browserError": "Error: {msg}",
    "browserAlreadyRunning": "Browser is already running",
    "browserLaunched": "Browser launched",
    "browserNotRunning": "Browser is not running",
    "browserClosed": "Browser closed",
    "browserNavigateNeedUrl": "navigate requires url parameter",
    "browserNavigated": "Navigated to {title}\nURL: {url}\n\n{snapshot}",
    "browserClickNeedRef": "click requires ref parameter",
    "browserClicked": "Clicked [{ref}]\n\n{snapshot}",
    "browserTypeNeedText": "type requires text parameter",
    "browserTyped": "Typed text{target}\n\n{snapshot}",
    "browserScrollNeedDir": "scroll requires direction parameter (up/down)",
    "browserScrolled": "Scrolled {dir}\n\n{snapshot}",
    "browserSelectNeedRef": "select requires ref parameter",
    "browserSelectNeedValue": "select requires value parameter",
    "browserSelected": "Selected [{ref}] → \"{value}\"\n\n{snapshot}",
    "browserKeyNeedKey": "key requires key parameter",
    "browserKeyPressed": "Pressed {key}\n\n{snapshot}",
    "browserWaitDone": "Wait complete\n\n{snapshot}",
    "browserEvalNeedExpr": "evaluate requires expression parameter",
    "browserOutputTruncated": "\n\n[... output truncated]",
    "browserShown": "Browser window brought to front",
    "browserUnknownAction": "Unknown action: {action}",
    "browserActionFailed": "Browser action failed: {msg}",
    "skillNeedAbsolutePath": "Absolute path required",
    "skillPathNotExists": "Path does not exist",
    "skillMissingSkillMd": "SKILL.md not found in folder",
    "skillUnsupportedFormat": "Only .zip or .skill files are supported",
    "skillMissingSkillMdInZip": "SKILL.md not found in archive",
    "skillExtractFailed": "Extraction failed: {msg}",
    "skillMissingName": "Missing name field in SKILL.md",
    "skillNameInvalid": "Invalid skill name (\"{name}\"). Only letters, numbers, underscores, and hyphens are allowed.",
    "skillPathMustBeAbsolute": "Path must be absolute: {path}",
    "skillCannotAddSelfDir": "Cannot add Hanako's own skills directory",
    "skillInvalidName": "Invalid skill name",
    "skillExternalCannotDelete": "External skills cannot be deleted from here",
    "skillNotExists": "Skill does not exist",
    "channelReadNeedChannel": "Error: read requires channel parameter",
    "channelNotExists": "Channel \"{channel}\" does not exist",
    "channelNoMessages": "(No messages in channel)",
    "channelPostNeedParams": "Error: post requires channel and content parameters",
    "channelPosted": "Sent to #{channel}",
    "channelCreateNeedParams": "Error: create requires name and members parameters",
    "channelCreated": "Channel #{name} ({id}) created, members: {members}",
    "channelCreateFailed": "Creation failed: {msg}",
    "channelNoJoined": "Not joined any channels yet",
    "unknownAction": "Unknown action: {action}",
    "cannotSelfDm": "Cannot send DM to yourself",
    "agentNotFoundAvailable": "Agent \"{id}\" not found. Available: {ids}",
    "dmSent": "DM sent to {name}",
    "cannotCallSelf": "Cannot call yourself",
    "agentNoReply": "({name} did not reply)",
    "agentCallFailed": "Calling {name} failed: {msg}",
    "cronNoJobs": "No scheduled tasks",
    "cronAddNeedParams": "Error: add requires type, schedule, prompt parameters",
    "cronEveryMustBeNumber": "Error: schedule for every type must be a positive integer (milliseconds)",
    "cronCreated": "Scheduled task created: {label} ({id})",
    "cronConfirmed": "User confirmed, scheduled task created: {label} ({id})",
    "cronRejected": "User cancelled scheduled task \"{label}\"",
    "cronTimeout": "Scheduled task \"{label}\" confirmation timed out",
    "cronPendingConfirm": "Ready to create scheduled task: {label}, awaiting confirmation",
    "cronRemoveNeedId": "Error: remove requires id parameter",
    "cronJobNotFound": "Task {id} not found",
    "cronRemoved": "Task {id} removed",
    "cronToggleNeedId": "Error: toggle requires id parameter",
    "cronToggled": "Task {id} {state}",
    "cronEnabled": "enabled",
    "cronDisabled": "disabled",
    "notifySent": "Notification sent: {title}",
    "notifyFailed": "Notification failed: {msg}",
    "todoNone": "No todos",
    "todoAddNeedText": "Error: add requires text parameter",
    "todoAdded": "Added todo #{id}: {text}",
    "todoToggleNeedId": "Error: toggle requires id parameter",
    "todoNotFound": "Todo #{id} not found",
    "todoToggled": "Todo #{id} {state}",
    "todoDone": "✓ Done",
    "todoUndone": "○ Not done",
    "todoCleared": "Cleared {count} todos",
    "artifactCreated": "Preview created: {title}",
    "pinnedAlreadyExists": "This is already in pinned memory.",
    "pinnedAdded": "Remembered: {content}",
    "pinnedEmpty": "Pinned memory is empty, nothing to remove.",
    "pinnedNotFound": "No pinned memory containing \"{keyword}\" found.",
    "pinnedRemoved": "Removed {count} items: {items}",
    "expEmpty": "Experience library is empty.",
    "expCategoryNotFound": "No experience found for category \"{category}\".",
    "expEmptyInput": "Category name and experience content cannot be empty.",
    "expDuplicate": "This experience has already been recorded.",
    "expRecorded": "Experience recorded [{category}]: {content}",
    "outputFileNeedPaths": "filepaths array or filePath is required.",
    "outputFileNotAbsolute": "Path must be absolute: {path}",
    "outputFileNotFound": "File not found: {path}",
    "outputFilePresented": "Files presented: {summary}",
    "msgAgentNotFound": "Agent \"{id}\" not found. Available: {ids}",
    "msgAgentNoReply": "({name} did not reply)",
    "settingsUnknownKey": "Unknown setting \"{key}\". Use search to find the correct key.",
    "settingsInvalidValue": "\"{value}\" is not a valid option. Available: {options}",
    "settingsInvalidToggle": "Toggle settings only accept \"true\" or \"false\".",
    "settingsNotReady": "Settings system not ready",
    "settingsApplied": "Changed \"{label}\" to {value}",
    "settingsApplyFailed": "Settings change failed: {msg}",
    "settingsCancelled": "User cancelled change of \"{label}\"",
    "settingsTimeout": "\"{label}\" change confirmation timed out, no changes made",
    "delegateMaxConcurrent": "{max} sub-tasks are already running, please wait before starting new ones.",
    "delegateFailed": "Sub-task execution failed: {msg}",
    "delegateNoOutput": "(Sub-task produced no output)",
    "installSkillDisabled": "Self-learning skills not enabled. Please enable \"Allow Agent to create/install skills\" in settings.",
    "installSkillGithubDisabled": "GitHub skill fetching not enabled. Please enable \"Allow fetching skills from GitHub\" in settings.",
    "installSkillInvalidGithubUrl": "Invalid GitHub URL: {url}",
    "installSkillGithubApiFailed": "Cannot retrieve repo info (HTTP {status}). Please check the URL.",
    "installSkillGithubApiError": "GitHub API access failed: {msg}",
    "installSkillStarTooLow": "This repo only has {stars} stars (threshold {min}), installation rejected for safety.",
    "installSkillNoSkillMd": "SKILL.md not found in {owner}/{repo} (tried paths: {paths}).",
    "installSkillSafetyFailed": "[Security] Skill safety review failed, installation blocked.\nReason: {reason}\n\nPlease inform the user about the safety review failure and the specific reason. Users can disable safety reviews in settings (not recommended).",
    "installSkillNameInvalid": "Invalid skill name{name}. Only letters, numbers, underscores, and hyphens are allowed.",
    "installSkillSuccess": "Skill \"{name}\" installed successfully!\nSource: {source} (⭐ {stars} stars)\nReason: {reason}",
    "installSkillNeedInput": "Please provide github_url or skill_content (SKILL.md content).",
    "installSkillNeedName": "skill_name is required when using skill_content mode.",
    "installSkillSuccessLocal": "Skill \"{name}\" installed successfully!\nReason: {reason}",
    "installSkillSizeLimit": "Skill content exceeds size limit ({size}KB > {max}KB)",
    "installSkillNoUtility": "Safety review unavailable: utility model not configured. Please configure it in settings.",
    "installSkillUtilityIncomplete": "Safety review unavailable: utility model config incomplete (missing API key or base URL). Please complete it in settings.",
    "installSkillSafetyPassed": "✓ Safety review passed",
    "installSkillSafetyEmpty": "Safety review returned empty response",
    "installSkillSafetyUnexpected": "Safety review returned unexpected format: {reply}",
    "installSkillSafetyTimeout": "Safety review timeout or network error",
    "activeSessionOnly": "Can only promote sessions of the current agent",
    "heartbeatTriggered": "Heartbeat triggered",
    "dirNotAllowed": "Directory not in allowed scope",
    "noWorkspace": "No workspace configured",
    "tokenSuccess": "Token obtained successfully",
    "verifyFailed": "Verification failed",
    "tokenFetchFailed": "Failed to obtain access_token",
    "botInfoFailed": "Failed to get bot info",
    "platformTestUnsupported": "Testing not supported for this platform",
    "codexNoHealthCheck": "Codex API does not support health check",
    "modelNotFound": "Model not found: {id}",
    "noUtilityModel": "Utility model not configured, please add one in settings",
    "noUtilityLargeModel": "utility_large model not configured, please add one in settings",
    "modelNoProvider": "{role} model \"{model}\" has no provider association",
    "providerMissingApi": "Provider \"{provider}\" missing API protocol config",
    "providerMissingCreds": "Provider \"{provider}\" missing credentials",
    "utilityApiProviderMismatch": "utility_api.provider must match the provider of model \"{model}\"",
    "utilityApiMissingCreds": "utility_api missing credentials (provider: {provider})",
    "noAvailableModel": "No available models. Please configure API key and models in settings first",
    "noActiveSessionPrompt": "No active session, please call createSession() first",
    "sessionNotInCache": "Session \"{path}\" not in cache",
    "agentNotInitialized": "Agent \"{id}\" does not exist or is not initialized",
    "resolveModelNoChatModel": "resolveModel: models.chat not specified, cannot select model",
    "resolveModelNotAvailable": "resolveModel: Model \"{id}\" not in available list",
    "executeIsolatedNoModel": "executeIsolated: Agent \"{name}\" has no available model",
    "bridgeAgentNoChatModel": "[bridge] Agent \"{name}\" has no models.chat configured",
    "bridgeAgentModelNotAvailable": "[bridge] Model \"{model}\" configured for agent \"{name}\" is not in available list",
    "noAgentsFound": "No agents found in agents/ directory, please create one first",
    "channelNotFoundById": "Channel \"{id}\" does not exist",
    "channelAlreadyExists": "Channel \"{id}\" already exists",
    "providerMissingBaseUrl": "Provider \"{provider}\" missing Base URL",
    "providerMissingApiKey": "Provider \"{provider}\" missing API Key",
    "modelNameEmpty": "Model name cannot be empty",
    "modelNotRegistered": "Model \"{model}\" not registered with any provider in models.json",
    "modelProviderMissingApi": "Provider \"{provider}\" for model \"{model}\" missing API protocol config",
    "modelProviderIncomplete": "Provider \"{provider}\" for model \"{model}\" has incomplete config",
    "browserDesktopOnly": "Browser is only available in Electron desktop mode",
    "browserCmdTimeout": "Browser command timed out: {cmd}",
    "agentExecNotInit": "Agent \"{id}\" does not exist or is not initialized",
    "bridgeMgrNotStarted": "Bridge manager not started",
    "qqTokenFailed": "Failed to get access_token: {detail}",
    "missingApiProtocol": "Missing API protocol config",
    "missingApiKey": "Missing API Key",
    "unsupportedApiProtocol": "Unsupported API protocol: {api}",
    "missingModelId": "Missing model ID",
    "missingBaseUrl": "Missing Base URL",
    "llmInvalidJson": "LLM returned unparseable JSON ({status})",
    "llmEmptyResponse": "LLM returned empty content",
    "xlsxParseFailed": "Cannot parse {ext} file: {msg}",
    "compatDirCreated": "Created {count} missing directories",
    "compatConfigEmpty": "File is empty",
    "compatConfigInvalid": "Does not appear to be YAML format",
    "compatConfigCorrupted": "config.yaml corrupted ({msg}), rebuilt from template",
    "compatConfigBackedUp": "config.yaml corrupted ({msg}), backed up as {backup}",
    "compatFactsCorrupted": "facts.db corrupted and backed up, will rebuild empty database",
    "defaultChannelName": "Crew",
    "defaultChannelDesc": "Work coordination channel for daily tasks.",
    "memorySearchLabel": "Search Memory",
    "memorySearchDesc": "Search the memory bank. Use when you are unsure about something, think you discussed it before but cannot recall details, or need more context. Input natural language queries and optional tag filters. Results include matching meta-facts and timestamps.",
    "memorySearchQueryDesc": "Search query in natural language",
    "memorySearchTagsDesc": "Tag filter, 2-5 keyword tags for precise matching, e.g. [\"chocolate\", \"food preference\"]",
    "memorySearchDateFromDesc": "Start date, format YYYY-MM-DD",
    "memorySearchDateToDesc": "End date, format YYYY-MM-DD",
    "memorySearchEmpty": "No relevant content found in memory.",
    "memorySearchError": "Memory search error: {msg}",
    "fallbackUserName": "User"
  },
  "main": {
    "tray": {
      "show": "Show Hanako",
      "settings": "Settings",
      "quit": "Quit"
    },
    "dialog": {
      "selectFolder": "Select Working Folder",
      "selectSkill": "Select Skill",
      "launchFailedTitle": "Hanako Launch Failed",
      "launchFailedBody": "{detail}\n\nDetailed log saved to:\n{logPath}\n\nPlease send this screenshot or log file to the developer.",
      "serverRestartFailed": "Server crashed and failed to restart.\n{error}\n\nPlease restart the application.",
      "serverMultipleCrash": "Server crashed multiple times ({reason}).\n\nPlease restart the application.",
      "serverStartTimeout": "Server start timed out (60s)",
      "serverKilledBySignal": "Server killed by signal ({signal})",
      "serverExitedWithCode": "Server exited with code {code}"
    },
    "notification": {
      "ready": "Notifications enabled"
    }
  },
  "devtools": {
    "heartbeat": "Heartbeat",
    "memoryExport": "Memory Export",
    "onboarding": "Onboarding",
    "previewGuide": "Preview Guide",
    "reloadFrontend": "Reload Frontend",
    "tabLogs": "Activity Logs",
    "tabSessions": "Session List",
    "tabPrompt": "System Prompt",
    "waitingConnection": "Waiting for connection...",
    "waitingServer": "Waiting for Server...",
    "loading": "Loading...",
    "loadFailed": "Load failed",
    "refreshBtn": "Refresh",
    "clickRefresh": "Click Refresh above to load",
    "noActivities": "No activities yet",
    "heartbeatLabel": "Auto heartbeat",
    "cronLabel": "Scheduled task",
    "heartbeatRunning": "Heartbeat running...",
    "heartbeatGenerating": "Generating summary...",
    "heartbeatDone": "Heartbeat completed",
    "heartbeatNoSummary": "Heartbeat completed (no summary)",
    "memoryExported": "Memory exported",
    "exportFailed": "Export failed",
    "onboardingOpened": "Onboarding window opened",
    "previewOpened": "Preview mode opened",
    "openFailed": "Open failed",
    "frontendReloaded": "Frontend reloaded",
    "refreshFailed": "Refresh failed",
    "triggerFailed": "Trigger failed",
    "requestFailed": "Request failed",
    "justNow": "Just now",
    "minutesAgo": "{n} min ago",
    "hoursAgo": "{n} hr ago",
    "chars": " chars",
    "empty": "empty",
    "serverConnected": "Server connected (port {port})"
  },
  "skillViewer": {
    "cantRead": "Cannot read file",
    "copied": "Copied to skill list",
    "installFailed": "Install failed: "
  },
  "toolDef": {
    "webSearch": {
      "label": "Web Search",
      "description": "Search the internet for real-time information. Use when you need the latest news, technical docs, current events, or any external knowledge not in memory.",
      "queryDesc": "Search keywords",
      "maxResultsDesc": "Number of results to return, default 5"
    },
    "webFetch": {
      "label": "Fetch Web Page",
      "description": "Fetch the content of a given URL and extract text. Useful for reading articles, docs, API responses, etc. Pair with web_search: first search to find a URL, then use web_fetch to read the full content.",
      "urlDesc": "Full URL to fetch (including https://)",
      "maxLenDesc": "Maximum characters to return, default {max}"
    },
    "browser": {
      "label": "Browser",
      "description": "Control a browser to browse the web. Supports navigation, clicking, typing, scrolling, and screenshots.\nActions:\n- start: Launch the browser (must be called before first use)\n- stop: Close the browser\n- navigate(url): Navigate to a URL\n- snapshot: Get the current page's element tree (recommended: text format, low cost)\n- screenshot: Take a screenshot of the current page (use only when visual info is needed)\n- click(ref): Click the element with the [ref] number from snapshot\n- type(text, ref?): Type text into an element, optionally click ref to focus first\n- scroll(direction, amount?): Scroll the page, direction is up/down\n- select(ref, value): Select a dropdown option\n- key(key): Press a key, e.g. Enter, Escape, Tab, Control+a\n- wait(timeout?, state?): Wait for the page to load\n- evaluate(expression): Execute JavaScript on the page\n- show: Bring the browser window to front\n\nImportant: [ref] numbers from snapshot become invalid after page changes. A new snapshot is automatically returned after each navigate/click.",
      "actionDesc": "Action type",
      "urlDesc": "URL (required for navigate)",
      "refDesc": "Element ref number (used for click/type/select)",
      "textDesc": "Input text (required for type)",
      "directionDesc": "Scroll direction (required for scroll)",
      "amountDesc": "Scroll amount (optional for scroll, default 3)",
      "valueDesc": "Option value (required for select)",
      "keyDesc": "Key name (required for key), e.g. Enter, Escape, Tab, Control+a",
      "expressionDesc": "JavaScript expression (required for evaluate)",
      "timeoutDesc": "Timeout in milliseconds (optional for wait, default 5000)",
      "stateDesc": "Wait state (optional for wait): domcontentloaded / idle",
      "pressEnterDesc": "Press Enter after typing (optional for type)"
    },
    "channel": {
      "label": "Channel",
      "description": "Manage channel messages (for broadcasts and group discussions).\nActions:\n- read(channel, count?): View recent messages in a channel\n- post(channel, content): Send a message to a channel\n- create(name, members, intro?): Create a new channel\n- list: View channels you have joined\nNote: For one-on-one messaging with an agent, use the dm tool instead of simulating a private chat via channels.",
      "actionDesc": "Action type",
      "channelDesc": "Channel name (required for read/post)",
      "contentDesc": "Message content (required for post)",
      "nameDesc": "New channel name (required for create)",
      "membersDesc": "Member list (required for create), e.g. [\"hana\", \"butter\"]",
      "introDesc": "Channel description (optional for create)",
      "countDesc": "Number of messages to read (optional for read, default 20)"
    },
    "artifact": {
      "label": "Create Preview",
      "description": "Call this tool when you need to show the user an HTML page, code snippet, or long-form Markdown content.\nContent is rendered in a standalone preview panel where the user can view results in real time.\nGood for: runnable HTML/CSS/JS pages, interactive visualizations, SVG charts, complete code files, long formatted documents.\nNot for: short text replies, conversational answers, one-line code snippets (just show those inline).",
      "typeDesc": "Content type: html (rendered page), code (syntax highlighted), markdown (document)",
      "titleDesc": "Display title, a short description of the content",
      "contentDesc": "Full content (HTML source / code / Markdown text)",
      "languageDesc": "Programming language (only for type=code), e.g. javascript, python, css"
    },
    "askAgent": {
      "label": "Cross-Agent Call",
      "description": "Assign a task to another agent and get an immediate result. The other agent processes it on the spot and responds, and you can relay the result to the user.\nGood for: having the other agent review code, translate text, analyze a problem from their expertise, or any task requiring instant feedback.\nThe other agent responds with its own persona and model, has read-only tools (read files, search, web fetch), and cannot write files or call other agents.",
      "agentDesc": "Target agent's ID",
      "taskDesc": "Task description (the full prompt the other agent sees)"
    },
    "dm": {
      "label": "Direct Message",
      "description": "Send a single direct message to another agent to inform them of something.\nDo not use this tool to assign tasks or get results; that is ask_agent's job.",
      "toDesc": "Target agent's ID",
      "messageDesc": "Message content"
    },
    "messageAgent": {
      "label": "Message Agent",
      "description": "Send a direct message to another agent and wait for a reply. Use when you need to consult or coordinate with another agent.\nThe other agent responds based on their own persona and config. The conversation takes place in a DM space, not through channels.\nImportant: Messages are sent as yourself, not on behalf of the user. For example, if the user says 'go chat with ming', write in your own voice (e.g. 'ming, how's it going?'), not 'the user wants to chat with you'.",
      "toDesc": "Target agent's ID (e.g. \"butter\")",
      "messageDesc": "Message content to send",
      "maxTurnsDesc": "Maximum number of back-and-forth turns, default 3. The other agent can end early with <done/>."
    },
    "cron": {
      "label": "Scheduled Tasks",
      "description": "Create and manage scheduled tasks. Scheduled tasks run automatically in the background, spawning an independent session to execute the specified prompt when triggered.\nActions:\n- list: View all tasks\n- add(type, schedule, prompt, label?, model?): Create a task\n  - type \"at\": One-time, schedule is an ISO time string\n  - type \"every\": Interval, schedule is milliseconds (e.g. 3600000 = 1 hour)\n  - type \"cron\": Cron expression (e.g. \"0 7 * * *\" = every day at 7 AM)\n  - model: Optional, specify the model for task execution (defaults to the chat model)\n- remove(id): Delete a task\n- toggle(id): Enable/disable a task",
      "actionDesc": "Action type",
      "typeDesc": "Schedule type (required for add)",
      "scheduleDesc": "Schedule parameter: ISO time (at), milliseconds (every), cron expression (cron)",
      "promptDesc": "Prompt to execute when triggered (required for add)",
      "labelDesc": "Task display label (optional)",
      "modelDesc": "Specify execution model (optional, defaults to the chat model)",
      "idDesc": "Task ID (required for remove/toggle)"
    },
    "notify": {
      "label": "Notification",
      "description": "Send a system notification (desktop popup) to the user.\nUse cases:\n- The user says 'remind me about xxx', 'notify me when...', 'don't let me forget xxx'\n- A scheduled task prompt explicitly includes notification intent\n- A monitoring/scheduled task discovers something requiring user attention\nIf everything is normal with no issues, do not call this tool.",
      "titleDesc": "Notification title (brief)",
      "bodyDesc": "Notification content"
    },
    "todo": {
      "label": "Todo",
      "description": "Manage a todo list within the current session. Use this tool to track progress and break down sub-tasks when performing multi-step tasks.\nActions:\n- list: View all todos\n- add(text): Add a todo item\n- toggle(id): Toggle completion status\n- clear: Clear all todos",
      "actionDesc": "Action type",
      "textDesc": "Todo content (required for add)",
      "idDesc": "Todo ID (required for toggle)"
    },
    "pinnedMemory": {
      "pinLabel": "Pin Memory",
      "pinDescription": "Save an item to pinned memory. Use when the user says 'remember this', 'note this down', 'don't forget this later'. Pinned memories are always kept in context.",
      "pinContentDesc": "Content to remember",
      "unpinLabel": "Unpin Memory",
      "unpinDescription": "Remove an item from pinned memory. Use when the user says 'forget xxx' or 'delete this memory'. Supports fuzzy matching: any line containing the keyword you provide will be removed.",
      "unpinKeywordDesc": "Keyword of the memory to remove, matched fuzzily"
    },
    "experience": {
      "recallLabel": "Recall Experience",
      "recallDescription": "Browse the experience library. Without parameters, returns an overview of all categories. With a category name, returns specific experiences in that category. When the user asks you to do a concrete task (write code, research, create documents, analyze problems, etc.), check this tool first for relevant experience before starting. Not needed for casual chat, Q&A, or everyday conversation.",
      "recallCategoryDesc": "Category name. Omit to get an overview of all categories",
      "recordLabel": "Record Experience",
      "recordDescription": "Record a lesson learned to the experience library. Use when: the user points out a mistake and explains the correct approach, you discover an effective method after trying multiple approaches, or the user explicitly says 'from now on do/don't do this'. Each entry should be concise and direct, one sentence.",
      "recordCategoryDesc": "Category for the experience, a 2-4 word phrase, e.g. 'tool usage', 'search tips', 'response style'",
      "recordContentDesc": "The specific experience content, concise and direct, one sentence"
    },
    "outputFile": {
      "label": "Present Files",
      "description": "After successfully creating files for the user (PDF, Word, Excel, PPT, Markdown, etc.), call this tool to present them in the conversation so the user can click to open. Only call after files have actually been written to disk; do not call if file creation failed. The first path should be the file the user most wants to see. Don't just mention file paths in text — call this tool.",
      "filepathsDesc": "Array of absolute file paths to present to the user",
      "filePathDesc": "(Compat) Single file absolute path",
      "labelDesc": "(Compat) File name shown to the user"
    },
    "delegate": {
      "label": "Delegate Sub-task",
      "description": "Delegate an independent sub-task to a background agent. The sub-task runs in an isolated context and only returns the final result, without consuming the current conversation's context.\nGood for:\n- Research tasks that require extensive searching and reading, summarized into a brief conclusion\n- Independent sub-problems that can run in parallel with your current work\n- Tasks that need simultaneous exploration in multiple directions (you can fire multiple delegate calls at once)\nNot for: Operations with side effects like modifying files or executing commands\n\nImportant: The task parameter must contain complete instructions and necessary background, as the sub-task cannot see the current conversation history.",
      "taskDesc": "Full instructions for the sub-task, including necessary background",
      "modelDesc": "Specify model (optional, defaults to utility model)"
    },
    "installSkill": {
      "label": "Install Skill",
      "description": "Install a new skill for yourself. Mode A: Provide a GitHub repo URL (containing SKILL.md) to auto-fetch and install. Mode B: Directly provide skill_content + skill_name, for self-authored skills. The skill takes effect immediately after installation.",
      "githubUrlDesc": "GitHub repo URL (Mode A)",
      "skillContentDesc": "Full content of SKILL.md (Mode B)",
      "skillNameDesc": "Skill name (required for Mode B)",
      "reasonDesc": "Explain why this skill is needed (for audit, required)"
    },
    "updateSettings": {
      "label": "Settings",
      "description": "Modify Hanako's settings. Two actions available:\n- search + query: Search settings by keyword, see current values and options\n- apply + key + value: Change a setting (requires user confirmation)\n\nIf you already know the exact key, you can apply directly.",
      "actionDesc": "Action: search to find settings / apply to change a setting",
      "queryDesc": "Search keyword (required for search)",
      "keyDesc": "Setting key (found via search)",
      "valueDesc": "Proposed new value",
      "searchResult": "Found {count} matching setting(s):\n\n{results}\n\nUse action \"apply\" with key and value to change a setting.",
      "searchNoResults": "No settings matching \"{query}\". Try a broader keyword.",
      "searchMissingQuery": "The search action requires a query parameter.",
      "applyMissingParams": "The apply action requires both key and value parameters.",
      "frontendOnly": "client-side only",
      "sandbox": "Sandbox Security",
      "sandboxDesc": "Restrict file system write scope",
      "locale": "Language",
      "timezone": "Timezone",
      "timezoneDesc": "IANA timezone (e.g. Asia/Shanghai)",
      "thinkingBudget": "Thinking Depth",
      "memory": "Memory System",
      "memoryDesc": "Enable/disable memory for current Agent",
      "agentName": "Agent Name",
      "userName": "User Name",
      "workingDir": "Working Directory",
      "workingDirDesc": "Agent file system working directory",
      "theme": "Theme",
      "chatModel": "Chat Model"
    }
  },
  "cli": {
    "disconnected": "Disconnected",
    "wsError": "WebSocket error: {msg}",
    "error": "Error: {msg}",
    "interrupted": "(interrupted)",
    "goodbye": "Goodbye ✿",
    "helpTitle": "Command List",
    "helpModel": "View current model",
    "helpModelSet": "Switch model (interactive)",
    "helpConfig": "View config",
    "helpSessionNew": "New session",
    "helpSessionList": "List sessions",
    "helpAgent": "View current agent",
    "helpAgentList": "List all agents",
    "helpAgentSwitch": "Switch agent",
    "helpJian": "View notes in current directory",
    "helpJianSub": "View notes in subdirectory",
    "helpLs": "List desk files",
    "helpLsSub": "List subdirectory files",
    "helpCat": "View file content",
    "helpHelp": "Show this help",
    "helpEsc": "Interrupt generation",
    "helpCtrlC": "Interrupt / Exit",
    "noModels": "No available models",
    "availableModels": "Available models:",
    "currentModel": "← current",
    "selectModel": "Enter number to select: ",
    "modelSwitched": "Switched to {name}",
    "cancelled": "Cancelled",
    "currentModelLabel": "Current model:",
    "noModel": "(none)",
    "currentConfig": "Current Config",
    "notSet": "(not set)",
    "sessionCreated": "New session created",
    "noSessions": "No sessions",
    "sessionList": "Session List",
    "untitled": "(untitled)",
    "sessionUsage": "Usage: /session new | /session list",
    "agentList": "Agent List",
    "agentSwitched": "Switched to {name}",
    "currentAgent": "Current Agent:",
    "jianTitle": "Notes",
    "jianEmpty": "No notes in this directory",
    "dirEmpty": "(empty)",
    "catUsage": "Usage: /cat <file path>",
    "catFailed": "Cannot read: {status}",
    "unknownCommand": "Unknown command: /{cmd}  Type /help for help",
    "inputHelp": "Type /help to see commands"
  },
  "sandbox": {
    "blocked": "[Security] {reason}\n\nThis operation was blocked by Hanako's sandbox security policy. This is not a bug, but a security protection mechanism at work. Please inform the user that the operation was blocked and explain the reason. Users can adjust sandbox policy in settings.",
    "noSudo": "sudo is not allowed",
    "noSu": "su user switching is not allowed",
    "noChmod": "Changing file permissions is not allowed",
    "noChown": "Changing file ownership is not allowed",
    "noDelRecursive": "Recursive file deletion (del /s) is not allowed",
    "noRmdirRecursive": "Recursive directory deletion (rmdir /s) is not allowed",
    "noRegEdit": "Registry modification is not allowed",
    "noTakeown": "Taking file ownership is not allowed",
    "noIcacls": "Modifying file ACL permissions is not allowed",
    "noNetUser": "User/group management is not allowed",
    "noSchtasks": "Creating scheduled tasks is not allowed",
    "noScService": "Operating system services is not allowed",
    "noPsExecutionBypass": "Bypassing PowerShell execution policy is not allowed",
    "noFormat": "Formatting disks is not allowed",
    "noBcdedit": "Modifying boot configuration is not allowed",
    "noWmic": "WMI commands are not allowed",
    "restrictedPath": "Command accessed a restricted path: {path}",
    "writeRestricted": "[Security] File system writes are restricted to the workspace. This operation was blocked by sandbox security policy. Please inform the user.",
    "osRequired": "[sandbox] Standard mode requires OS-level sandbox, but current platform does not support it ({platform}). Please install sandbox-exec (macOS) or bubblewrap (Linux), or switch to full-access mode.",
    "opRead": "Read",
    "opWrite": "Write",
    "opDelete": "Delete",
    "denied": "{op} denied: {path} (access level: {level})"
  },
  "error.llmTimeout": "Model request timed out",
  "error.llmRateLimited": "Model rate limited, please wait",
  "error.llmEmptyResponse": "Model returned empty response",
  "error.llmAuthFailed": "Model authentication failed",
  "error.llmSlowResponse": "Model is responding slowly, please wait",
  "error.fsPermission": "File permission denied",
  "error.fsNotFound": "File not found",
  "error.fsCopyFailed": "File copy failed",
  "error.wsDisconnected": "Connection lost",
  "error.fetchTimeout": "Request timed out",
  "error.fetchServerError": "Server error",
  "error.ipcFailed": "Internal communication error",
  "error.renderCrash": "Display error",
  "error.configParse": "Configuration file corrupted",
  "error.bridgeSendFailed": "Failed to send message to platform",
  "error.skillSyncFailed": "Skill sync failed",
  "error.memoryCompileFailed": "Memory compilation failed",
  "error.dbError": "Database error",
  "error.serverAuthFailed": "Authentication failed",
  "error.unknown": "An unexpected error occurred",
  "error.regionUnavailable": "This area is temporarily unavailable",
  "status.reconnecting": "Reconnecting...",
  "status.disconnected": "Connection lost",
  "status.reconnect": "Reconnect",
  "action.retry": "Retry"
}
