{
  "channel": {
    "tab": "Channels",
    "chatTab": "Chat",
    "empty": "No channels yet ✿",
    "dmLabel": "Messages",
    "dmHint": "Only real internal DMs with messages are shown",
    "groupLabel": "Channels",
    "noMessages": "No messages yet",
    "selectHint": "Select a channel or DM to start",
    "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",
    "createBaseAgent": "Current assistant included",
    "createSelectAdvisors": "Select advisors to add",
    "createNeedAssistant": "No assistant is available to create a channel",
    "createNeedAdvisor": "Select at least one advisor",
    "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",
    "archiveChannel": "Archive channel",
    "archiveAction": "Archive",
    "archiveConfirm": "Archive channel \"{name}\"? It will become read-only, but the full history will be kept.",
    "archived": "Channel archived",
    "archiveFailed": "Archive failed",
    "archivedLabel": "Archived",
    "archivedBadge": "Archived",
    "archivedStatus": "Archived",
    "archivedReadOnly": "🔒 Archived channels are read-only",
    "deleteChannel": "Delete channel",
    "deleteConfirm": "Delete channel \"{name}\"? Message history cannot be recovered.",
    "deleted": "Channel deleted",
    "deleteFailed": "Delete failed",
    "addMember": "Add member",
    "addMemberTitle": "Add Members",
    "addMemberAgents": "Existing Agents",
    "addMemberExperts": "Expert Presets",
    "addMemberConfirm": "Add",
    "addMemberFailed": "Add failed",
    "addMemberNone": "All agents are already in this channel",
    "memberAdded": "Member added",
    "expertSelectHint": "Choose an expert, pick a model, then confirm to add them",
    "expertConfigTitle": "Expert to add",
    "expertSelected": "Selected",
    "expertModelAuto": "Default (recommended / current available)",
    "expertRecommendedModel": "Recommended model",
    "expertModelFallback": "If not specified, the recommended or current available model will be used",
    "expertAdding": "Working...",
    "expertCreating": "Creating...",
    "expertCreateChannel": "Create a channel with them",
    "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",
    "expertTeam": {
      "guideTitle": "Build an Expert Team",
      "guideDesc": "Let AI with different expertise discuss together for better solutions",
      "guideTip": "You can also click + in the top right to create a custom channel",
      "needMoreAgents": "Please create at least 1 Agent first",
      "creating": "Creating...",
      "expertPresets": "Expert Presets (Uses Your API Key)",
      "channelTemplates": "Channel Templates (Uses Existing Agents)",
      "roundtableTitle": "Roundtable",
      "roundtablePlaceholder": "For example: discuss the next step for this project",
      "roundtableHint": "Lynn will create multiple experts first, then start a shared discussion channel for them.",
      "roundtableCreate": "Start roundtable",
      "spawnSuccess": "Expert created",
      "spawnFailed": "Failed to create expert",
      "modelGuide": "💡 Experts run on your configured model. Recommended models are shown on cards — configure the corresponding API Key in Settings → Models for best results.",
      "tpl": {
        "codeReview": {
          "label": "Code Review Team",
          "desc": "Security expert, performance expert & architect review code together",
          "intro": "This is a code review channel. Please review from your professional perspective:\n- Focus on security vulnerabilities, injection risks, permission issues\n- Focus on performance bottlenecks, memory leaks, algorithm complexity\n- Focus on architecture design, maintainability, extensibility\nPlease share your expert opinions and discuss with each other."
        },
        "productBrainstorm": {
          "label": "Product Brainstorm",
          "desc": "Product manager, designer & engineer discuss requirements together",
          "intro": "This is a product brainstorming channel. Please discuss from your role's perspective:\n- Product: user needs, market positioning, priorities\n- Design: user experience, interaction flow, visual style\n- Engineering: technical feasibility, development cost, implementation\nPlease actively contribute and brainstorm the best solution."
        },
        "archDiscussion": {
          "label": "Architecture Discussion",
          "desc": "Backend, frontend & DevOps experts discuss tech decisions",
          "intro": "This is an architecture discussion channel. Please discuss from your domain:\n- Backend: API design, data models, service architecture\n- Frontend: component design, state management, performance\n- DevOps: deployment strategy, CI/CD, monitoring & alerts\nPlease thoroughly discuss pros and cons to reach consensus."
        }
      }
    },
    "disabled": "Channels disabled",
    "toggleLabel": "Channel toggle",
    "members": "Members",
    "createIntroOptional": "Description"
  },
  "expert": {
    "yuanStyle": "Thinking style",
    "recommendedModel": "Recommended model (configure API Key in Settings)",
    "modelTip": "Currently uses your default model. Configure the recommended model's API Key for best results."
  },
  "sidebar": {
    "title": "Chats",
    "newChat": "New Chat",
    "collapse": "Collapse sidebar",
    "expand": "Expand chat list",
    "empty": "No chats yet ✿",
    "emptyAction": {
      "organize": "Organize files",
      "organizePrompt": "Help me organize the files in the current workspace. Categorize them and give suggestions.",
      "plan": "Write a task list",
      "planPrompt": "Help me write a task list for today. List the top 3 most important things.",
      "analyze": "Analyze a file",
      "analyzePrompt": "I want to analyze a file. Tell me to drag it in or use @ to reference it."
    },
    "activity": "Activity",
    "jian": "Desk",
    "bridge": "Social Platforms",
    "toggle": "Sidebar",
    "bridgeShort": "Bridge",
    "capability": {
      "web": "web search",
      "files": "file edits",
      "shell": "terminal runs",
      "instructions": "project instructions loaded",
      "mcp": "MCP ready",
      "skills": "Skills",
      "automation": "Automations",
      "assistants": "Assistants",
      "todo": "Todo",
      "done": "Done",
      "skillsCenter": "Skills",
      "mcpHub": "MCP",
      "projectRules": "Rules",
      "state": "Now",
      "model": "Model",
      "jian": "Jian",
      "continueBusy": "Tasks are still moving",
      "continueIdle": "Ready to start from this workspace",
      "tryAt": "Show a file with @",
      "startWorkspace": "Read workspace first",
      "resumeTask": "Resume task",
      "resumePrompt": "Continue the last task and tell me the current progress plus the next step first.",
      "workspacePrompt": "Quickly read the current workspace and tell me where you would start.",
      "fleetTip": "Fleet: split a task across parallel CLI workers, each in its own worktree"
    }
  },
  "titlebar": {
    "task": {
      "openActivity": "Open task details",
      "meta": "{count} active task(s)",
      "waiting": "{count} waiting",
      "waitingOne": "waiting approval",
      "waitingMany": "waiting approval",
      "running": "{count} running",
      "runningOne": "task running",
      "runningMany": "tasks running",
      "pending": "{count} queued",
      "pendingOne": "queued",
      "pendingMany": "queued"
    }
  },
  "session": {
    "untitled": "New Chat",
    "messageCount": "{n} messages",
    "switchFailed": "Failed to switch session",
    "createFailed": "Failed to create session",
    "archiveFailed": "Failed to archive session",
    "rename": "Rename",
    "editLabels": "Edit labels",
    "labelsPlaceholder": "Labels, comma separated",
    "pin": "Pin",
    "unpin": "Unpin",
    "pinned": "Pinned",
    "archive": "Archive",
    "archiveConfirm": "Archive “{name}”? It will be hidden from the list but history is kept.",
    "menuTrigger": "More actions"
  },
  "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",
    "delete": "Delete",
    "editResend": "Edit & resend",
    "editResendTitle": "Edit & resend (copies this message to the input; press Enter to resend after fixing)"
  },
  "chat": {
    "send": "Send",
    "steer": "Steer",
    "stop": "Stop",
    "browserScreenshot": "Browser screenshot",
    "compacting": "Compacting context",
    "needWsConnection": "Disconnected from the assistant. Wait for reconnect or tap Reconnect in the status bar.",
    "waitForCurrentReply": "The current reply is still running. Please wait for this turn to finish before sending another message.",
    "retry": "Retry",
    "emptyAnswerHint": "The model thought but didn't say anything. Tap retry to try again.",
    "emptyAnswerRetry": "Retry"
  },
  "markdown": {
    "runConfirm": {
      "title": "Run code block command",
      "message": "Lynn will run this command for you.",
      "cwd": "Working directory",
      "cwdUnknown": "Not set",
      "risk": "Risk",
      "confirm": "Run"
    },
    "runRisk": {
      "low": "Low",
      "medium": "Medium",
      "high": "High"
    }
  },
  "review": {
    "button": "Review",
    "cardTitle": "Review",
    "noReviewer": "No reviewer agent available. Create a second agent first.",
    "configure": "Configure reviewer",
    "loading": "Loading",
    "auto": "Auto select",
    "needsConfig": "No reviewer is configured yet",
    "requestFailed": "Review request failed",
    "followUp": "Handle findings",
    "taskCreated": "Execution task created"
  },
  "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",
    "pinned": "Pinned"
  },
  "status": {
    "connecting": "Connecting...",
    "connected": "Connected",
    "disconnected": "Disconnected",
    "serverNotReady": "Server not ready",
    "loading": "Loading...",
    "reconnecting": "Reconnecting",
    "reconnect": "Reconnect",
    "usage": {
      "cache": "cache",
      "tip": "Cumulative cloud token spend for this session (incl. prefix-cache hits and cost estimate)"
    }
  },
  "input": {
    "placeholder": "Say something...",
    "hintAt": "Type @ to show Lynn a file",
    "hintSlash": "Type / for quick commands",
    "hintDrag": "Drop files here to add context",
    "hintAnalyzeExcel": "Help me analyze this Excel file...",
    "hintScanStock": "Scan today's stock market for unusual moves...",
    "hintOrganize": "Organize the documents in this folder...",
    "hintCmdK": "⌘K search chat history",
    "hintDesk": "⌘J open desk panel",
    "selectFolder": "Select folder",
    "workspace": "Workspace: ",
    "selectWorkspace": "Select workspace",
    "planMode": "Allow terminal & writes (off = read-only)",
    "deskContext": "With desk context",
    "pastedImage": "Pasted image",
    "attachFile": "Attach file",
    "docContext": "With document",
    "docContextOpenRecent": "Click to open a recent document",
    "embeddedModel": {
      "name": "Default model",
      "meta": "Ready to chat",
      "upgrade": "Connect model",
      "hint": "Add a provider or API key",
      "upgradeTitle": "Open provider settings"
    },
    "thinkingLevel": {
      "off": "off",
      "auto": "auto",
      "high": "high",
      "xhigh": "max",
      "autoHint": "auto: coding/reasoning turns run at high; tool-continuation rounds auto-drop to medium. Pick high to pin every round."
    },
    "thinkingDesc": {
      "off": "no reasoning",
      "auto": "Deep for coding/reasoning; tool follow-up rounds auto-step down",
      "high": "deep reasoning",
      "xhigh": "full reasoning"
    },
    "contextWindow": "Context {windowK}k",
    "tokensUsed": "Used {tokensK}k ({pct}%)",
    "contextOverview": "Context included this time",
    "contextOverviewSubtitle": "Quick check before send so the prompt carries exactly what you expect.",
    "contextMode": "Mode",
    "contextModel": "Model",
    "contextText": "Prompt",
    "contextTextValue": "{count} chars",
    "contextQuote": "Quoted selection",
    "atDiscovery": {
      "title": "Try @ to show Lynn a file",
      "subtitle": "For example: @App.tsx help me inspect this route",
      "searching": "Searching files...",
      "menuHint": "Pick a file or folder to bring into this chat",
      "inlineHint": "💡 Type @{name} to let Lynn see this file directly",
      "inlineAction": "Use @ reference"
    },
    "contextDoc": "Reference doc",
    "contextFiles": "Attachments",
    "contextImages": "Images",
    "contextHeldBack": "Kept in draft",
    "modeSend": "Send",
    "modeSteer": "Steer",
    "contextGit": "Git context"
  },
  "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...",
    "clear": "Clear current chat",
    "clearDone": "Chat cleared",
    "clearFailed": "Failed to clear",
    "plan": "Toggle plan mode",
    "model": "Switch model",
    "save": "Save checkpoint",
    "saveDone": "Checkpoint saved",
    "saveFailed": "Checkpoint save failed"
  },
  "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",
    "focusHint": "Press Cmd/Ctrl + K to start typing",
    "quickActions": {
      "askFolder": {
        "label": "Help me plan",
        "prompt": "I want to get clear on what to move forward today. Use the current workspace and note to give me a short execution plan and the best first step. If there's no note yet, help me create a task list."
      },
      "summarizeWork": {
        "label": "Analyze a file",
        "prompt": "I want to analyze a file. You can help me with Excel spreadsheets, PDF documents, CSV data, and more. Just tell me to drag the file in or use @ to reference it."
      },
      "planToday": {
        "label": "What should I do today?",
        "prompt": "First look at the current workspace and note, then tell me the top three things worth moving forward today and the best first step. If there is no note yet, help me create a short work list before asking follow-up questions."
      },
      "tryAt": {
        "label": "Try @ file context"
      },
      "fleet": {
        "label": "⚡ Run parallel workers"
      }
    }
  },
  "drop": {
    "hint": "Drop to send files to {name}",
    "mainHint": "Drop to analyze",
    "subHint": "{name} supports Excel, PDF, CSV, images and more"
  },
  "attach": {
    "folder": "Folder",
    "copy": "Copy",
    "copied": "Copied ✓"
  },
  "preview": {
    "openInBrowser": "Open in Browser",
    "exportPng": "Export PNG"
  },
  "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",
        "name": "Hanako"
      },
      "butter": {
        "label": "More expressive",
        "avatar": "Butter.png"
      },
      "kong": {
        "label": "Vanilla",
        "avatar": "Kong.png"
      },
      "lynn": {
        "label": "More dependable",
        "avatar": "Lynn.png",
        "name": "Lynn"
      }
    },
    "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"
      ],
      "lynn": [
        "{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"
      ],
      "lynn": [
        "Hello. Whenever you're ready.",
        "{name} is ready",
        "What needs handling?",
        "Go ahead, {name} is listening"
      ]
    },
    "placeholder": {
      "butter": "Say whatever's on your mind...",
      "lynn": "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"
    ],
    "done": "Thinking complete",
    "active": "Thinking",
    "lynn": [
      "Analyzing",
      "Running scenarios",
      "Fact-checking",
      "Organizing thoughts",
      "Tracing the logic",
      "Outlining in their head",
      "Retrieving relevant info",
      "Verifying",
      "Breaking down the problem",
      "Synthesizing"
    ]
  },
  "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 peeking at a webpage",
      "done": "📄 {name} got it all",
      "failed": "📄 {name} couldn't reach the page"
    },
    "stock_market": {
      "running": "📈 {name} is checking the markets",
      "done": "📈 {name} got the prices",
      "failed": "📈 {name} couldn't fetch prices"
    },
    "stock_research": {
      "running": "📊 {name} is pulling financials",
      "done": "📊 {name} read the report",
      "failed": "📊 {name} couldn't fetch financials"
    },
    "weather": {
      "running": "☀️ {name} is checking the weather",
      "done": "☀️ {name} got the weather",
      "failed": "☀️ {name} couldn't fetch the weather"
    },
    "live_news": {
      "running": "📰 {name} is scanning the news",
      "done": "📰 {name} read the news",
      "failed": "📰 {name} couldn't fetch news"
    },
    "sports_score": {
      "running": "⚽ {name} is checking scores",
      "done": "⚽ {name} got the scores",
      "failed": "⚽ {name} couldn't fetch scores"
    },
    "exchange_rate": {
      "running": "💱 {name} is checking exchange rates",
      "done": "💱 {name} got the rates",
      "failed": "💱 {name} couldn't fetch rates"
    },
    "express_tracking": {
      "running": "📦 {name} is tracking the package",
      "done": "📦 {name} got the status",
      "failed": "📦 {name} couldn't track it"
    },
    "calendar": {
      "running": "📅 {name} is doing the date math",
      "done": "📅 {name} worked it out",
      "failed": "📅 {name} couldn't compute"
    },
    "unit_convert": {
      "running": "🔢 {name} is converting units",
      "done": "🔢 {name} converted it",
      "failed": "🔢 {name} couldn't convert"
    },
    "create_report": {
      "running": "📋 {name} is drafting the report",
      "done": "📋 {name} finished the report",
      "failed": "📋 {name} couldn't generate the report"
    },
    "create_pdf": {
      "running": "📑 {name} is laying out the PDF",
      "done": "📑 {name} finished the PDF",
      "failed": "📑 {name} couldn't make the PDF"
    },
    "create_pptx": {
      "running": "🎬 {name} is building the deck",
      "done": "🎬 {name} finished the deck",
      "failed": "🎬 {name} couldn't make the deck"
    },
    "create_artifact": {
      "running": "🎨 {name} is composing the artifact",
      "done": "🎨 {name} finished the artifact",
      "failed": "🎨 {name} couldn't compose it"
    },
    "search_memory": {
      "running": "💭 {name} is trying to remember",
      "done": "💭 {name} remembered!",
      "failed": "💭 {name} can't seem to remember"
    },
    "bash": {
      "running": "Running command…",
      "done": "Command finished",
      "failed": "Command failed"
    },
    "read": {
      "running": "Reading file…",
      "done": "Read",
      "failed": "Read failed"
    },
    "write": {
      "running": "Writing file…",
      "done": "Written",
      "failed": "Write failed"
    },
    "edit": {
      "running": "Editing file…",
      "done": "Edited",
      "failed": "Edit failed"
    },
    "edit-diff": {
      "running": "Editing file…",
      "done": "Edited",
      "failed": "Edit failed"
    },
    "glob": {
      "running": "🔍 {name} is looking for files",
      "done": "🔍 {name} found them",
      "failed": "🔍 {name} searched high and low, nothing"
    },
    "grep": {
      "running": "🔍 {name} is rummaging through files",
      "done": "🔍 {name} found something",
      "failed": "🔍 {name} rummaged through everything, nope"
    },
    "find": {
      "running": "🔍 {name} is looking for files",
      "done": "🔍 {name} found them",
      "failed": "🔍 {name} searched high and low, nothing"
    },
    "ls": {
      "running": "📂 {name} is peeking inside a folder",
      "done": "📂 {name} all seen",
      "failed": "📂 {name} couldn't open this folder"
    },
    "truncate": {
      "running": "✂️ {name} is tidying up a file",
      "done": "✂️ {name} all tidied up",
      "failed": "✂️ {name} couldn't tidy up"
    },
    "present_files": {
      "running": "📎 {name} is preparing the file",
      "done": "📎 Here it is!",
      "failed": "📎 Couldn't hand it over"
    },
    "browser": {
      "running": "Browser…",
      "done": "Browser done",
      "failed": "Browser failed"
    },
    "_fallback": {
      "running": "🔧 {name} is busy working…",
      "done": "🔧 {name} all done",
      "failed": "🔧 {name} that didn't go as planned"
    }
  },
  "file_output": {
    "open": "Open",
    "copied": "Path copied"
  },
  "model": {
    "unknown": "Unknown model",
    "offline": "Offline",
    "switchFailed": "Failed to switch model",
    "switchAfterNewSession": "Please create a new session before switching models"
  },
  "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",
      "voice": "Voice",
      "mcp": "MCP",
      "plugins": "Add-ons",
      "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": "Lynn",
      "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 heartbeat and a good memory.",
      "license": "License",
      "copyright": "Copyright",
      "copyrightOriginal": " (Original)",
      "copyrightDerived": " (Derived Work)",
      "description": "Description",
      "descriptionText": "Developed based on liliMozi's open-source project",
      "licenseToggle": "License full text",
      "permissions": "Permissions",
      "fullAccess": "Full Access Mode",
      "fullAccessDesc": "Allow higher-privilege local execution and system operations (takes effect on new sessions)",
      "fullAccessWarningTitle": "About Full Access Mode",
      "fullAccessWarningBody1": "Once enabled, the agent will have full system privileges, including:",
      "fullAccessWarningBody2": "1. The agent can access a much broader set of local paths\n2. Terminal restrictions are greatly reduced, including sudo or chmod\n3. System-level changes may happen, so you should review the risk yourself",
      "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",
      "defaultProviderHint": "Switch between local Qwen3.5-9B and cloud providers in one click.",
      "openProviders": "Open Providers →"
    },
    "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",
      "defaultModelHint": "Lynn routes the default model in the background. You do not need to add, remove, or choose individual model IDs manually.",
      "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 will be removed.",
      "apiResponses": "OpenAI Responses",
      "apiCodex": "ChatGPT Codex (Plus/Pro)"
    },
    "mcp": {
      "title": "MCP Servers",
      "hint": "Manage local stdio and remote SSE MCP servers. Connected tools become available inside Lynn.",
      "presets": "Presets",
      "newServer": "New",
      "serverList": "Servers",
      "detail": "Details",
      "name": "Name",
      "nameRequired": "Please enter an MCP name",
      "transport": "Transport",
      "command": "Command",
      "args": "Arguments",
      "cwd": "Working Directory",
      "url": "SSE URL",
      "messageUrl": "Message URL (optional)",
      "headers": "Headers",
      "enabled": "Enable this server",
      "test": "Test Connection",
      "testSuccess": "Connection succeeded",
      "reload": "Reload",
      "reloaded": "MCP reloaded",
      "empty": "No MCP servers yet",
      "tools": "Tools",
      "resources": "Resources",
      "source": "Source",
      "local": "Local config",
      "discovered": "Discovered"
    },
    "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",
      "vision": "Vision",
      "reasoning": "Reasoning"
    },
    "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",
      "placeholder": "Search settings…",
      "empty": "No matching tabs"
    },
    "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",
      "trustedRoots": "Trusted roots",
      "trustedRootsDesc": "Paths that are allowed for workspace-level read and write in execute mode",
      "addTrustedRoot": "Add trusted path",
      "trustedRootsHint": "Add at least one project folder so Lynn only reads and writes inside places you explicitly trust.",
      "review": {
        "title": "Review chain",
        "desc": "Review now only picks from Hanako / Butter, never from unrelated channel or expert agents. Bind a dedicated agent for each reviewer so they can run on separate models.",
        "defaultReviewer": "Default reviewer",
        "defaultReviewerDesc": "The reviewer persona used first when you click review.",
        "hanakoTitle": "Hanako reviewer",
        "hanakoDesc": "Use for the careful default review pass.",
        "butterTitle": "Butter reviewer",
        "butterDesc": "Use for a second perspective with a different model if needed.",
        "chooseReviewer": "Choose reviewer agent",
        "createReviewer": "Create reviewer agent",
        "configureModel": "Configure model",
        "unboundHint": "No dedicated reviewer agent is bound yet.",
        "boundModel": "Current model: {provider} / {model}",
        "modelHint": "Each reviewer agent keeps its own model setting on the Agent tab. Hanako, Butter, and Lynn no longer need to share one large model.",
        "createSuccess": "Created reviewer agent: {name}"
      }
    },
    "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}\"?",
      "externalPathRemoveConfirm": "Remove this external skills path?\n{path}",
      "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"
      }
    },
    "plugins": {
      "title": "Add-ons",
      "desc": "Add-ons loaded in this instance.",
      "empty": "No add-ons available",
      "reload": "Reload",
      "statusLoaded": "loaded",
      "statusFailed": "failed",
      "statusDisabled": "disabled"
    },
    "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": "Set as your account",
      "ownerWarning": "Messages from this account will be handled as full Lynn access. Other accounts stay in guest mode.",
      "ownerNone": "Send a message first to select",
      "ownerPending": "Have this platform send Lynn one real message first. The \"Set as your account\" option will appear after Lynn recognizes the account.",
      "ownerSaved": "Saved",
      "ownerConfirmTitle": "Set as Owner?",
      "ownerConfirmText": "After this, messages from the selected account can use Lynn's full memory, tools, and persona. Make sure it is really 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"
    },
    "shortcuts": {
      "title": "Keyboard shortcuts",
      "globalSummon": "Global summon",
      "globalSummonHint": "Rebind in Voice settings. If the shortcut is taken by another app, Lynn falls back to Cmd/Ctrl+Opt+J."
    }
  },
  "onboarding": {
    "welcome": {
      "title": "Hi, I'm {name} ✿",
      "subtitle": "I'm your personal AI assistant.\nPick how you want to start, then we'll head straight into the app.",
      "next": "Get Started",
      "quickTitle": "Use it right away",
      "quickDesc": "Keep only the minimum steps.\nName is optional now; model and theme can wait.",
      "quickAction": "Enter Quick Start",
      "advancedTitle": "Configure everything now",
      "advancedDesc": "If you already know your provider and model,\nset up connection, model, and theme in one pass.",
      "advancedAction": "Enter Advanced Setup",
      "localTitle": "Local first (offline)",
      "localDesc": "Download the 5.78 GB / 5.38 GiB Lynn default model (Qwen3.5-9B Q4_K_M imatrix MTP),\nfully offline — no chats ever uploaded.",
      "localAction": "Download local model"
    },
    "name": {
      "title": "What should I call you?",
      "subtitle": "This makes our conversations more natural",
      "quickSubtitle": "You can fill it in now, or change it later in Settings",
      "placeholder": "Enter your name",
      "quickHint": "Leaving it blank is fine — just get inside first.",
      "avatarUpload": "Upload avatar (optional)",
      "avatarChange": "Change avatar",
      "avatarUploading": "Uploading…",
      "back": "Back",
      "next": "Next",
      "quickNext": "Continue Quick Start"
    },
    "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",
      "apiOpenai": "OpenAI Compatible",
      "apiAnthropic": "Anthropic Messages",
      "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...",
      "retry": "Retry",
      "errorFallbackTitle": "We can't reach {provider} right now",
      "errorFallbackSubtitle": "Want to try the free Brain v2 default instead?",
      "errorBack": "Pick another provider",
      "errorBrain": "Use Brain v2 fallback",
      "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",
      "settingsHint": "You can configure utility models later in Settings"
    },
    "theme": {
      "title": "Pick a Theme",
      "subtitle": "You can always change it later in Settings",
      "back": "Back",
      "next": "Next"
    },
    "permissions": {
      "title": "Set Permissions In One Pass",
      "subtitle": "Quick Start prepares a default workspace first: ~/Desktop/Lynn.\nIt also adds Desktop and the current install directory to the safe roots, then handles notifications in one pass.",
      "workspace": {
        "title": "Workspace",
        "desc": "By default Lynn creates a Lynn folder on your Desktop as the main workspace.\nPatrols, scheduled tasks, and file actions stay inside that workspace and other roots you explicitly approve.",
        "safeRoots": "Default safe roots",
        "selected": "Selected",
        "pending": "Needs setup",
        "placeholder": "Not chosen yet. We'll open the folder picker when you continue."
      },
      "notifications": {
        "title": "Notifications",
        "desc": "Notifications are only used when Lynn needs to get your attention. We ask here on purpose instead of popping it up during launch.",
        "detail": "If you skip it now, you can still enable notifications later in System Settings.",
        "status": {
          "checking": "Checking",
          "pending": "Not granted",
          "granted": "Enabled",
          "denied": "Denied",
          "unsupported": "No prompt needed"
        }
      },
      "note": "When you continue, Lynn will save the default workspace and safe roots, then request notification access only if macOS still needs it.",
      "back": "Back",
      "continue": "Authorize and Continue",
      "working": "Working..."
    },
    "localModel": {
      "title": "Download Lynn's default local model",
      "subtitle": "Qwen3.5-9B Q4_K_M imatrix MTP · 5.78 GB / 5.38 GiB · 32K context · 24GB+ RAM recommended.\nRuns fully offline — no API key, no data ever leaves your machine.",
      "specsLine": "5.78 GB / 5.38 GiB · Q4_K_M imatrix MTP · 32K context · fully offline",
      "needsBinary": "llama.cpp inference engine not found at ~/.lynn/llamacpp/bin/llama-server",
      "needsBinaryHint": "Install llama.cpp following the docs and retry.",
      "alreadyHave": "Local model is ready",
      "alreadyHaveDesc": "The model is already downloaded — you're good to go.",
      "startBtn": "Start download",
      "pauseBtn": "Pause",
      "resumeBtn": "Resume",
      "cancelBtn": "Cancel download",
      "retryBtn": "Retry download",
      "switchBackBtn": "Use Brain v2 default model instead",
      "downloading": "Downloading (source {source})",
      "verifying": "Verifying SHA-256…",
      "paused": "Paused",
      "ready": "Download complete ✿",
      "spawning": "Starting llama.cpp inference server…",
      "spawnReady": "llama.cpp is ready",
      "spawnFailed": "Inference server failed to start: {reason}",
      "errorChecksum": "Checksum mismatch — rotating to next mirror",
      "errorAll": "All mirrors failed — check your network and retry",
      "errorGeneric": "Download error: {reason}",
      "next": "Continue",
      "back": "Back",
      "modelPreparedHint": "Model and llama.cpp are ready. Click Start to switch to Local Qwen3.5-9B.",
      "statusReady": "Ready",
      "statusWaiting": "Pending",
      "runtimeLocal9B": "Local Qwen3.5-9B",
      "runtimeLocalDefault": "Local Qwen3.5-9B"
    },
    "tutorial": {
      "interactive": {
        "step1Title": "1 / 3 · Try sending a message",
        "step1Desc": "After you land in the main window, type something and press Enter. Lynn replies in a stream; press Esc to interrupt.",
        "step1Try": "Try it (preview only)",
        "step1Playing": "Playing preview…",
        "step2Title": "2 / 3 · Pick a working folder",
        "step2Desc": "The working folder is where Lynn patrols, reads/writes files, and runs automations. Pick one now — you can change it later in the main window.",
        "step2Try": "Pick folder now",
        "step2Selected": "Picked {folder}",
        "step3Title": "3 / 3 · Browse your chat history",
        "step3Desc": "Inside the main window, the left sidebar lists every conversation — jump back any time. Toggle the sidebar with ⌘1 / Ctrl+1.",
        "step3Hint": "The sidebar looks like this ↓"
      },
      "title": "All Set ✿",
      "quickTitle": "Quick Start is ready ✿",
      "quickBannerTitle": "One core idea: jian is today's work file",
      "quickBannerDesc": "Write today's direction into jian.md inside the workspace.\nPatrol keeps rereading it, memory keeps the stable background, and the activity panel shows how far Lynn has already moved the work.",
      "memory": {
        "title": "Memory",
        "desc": "Memory is not a second todo list. It is the long-term background Lynn carries while working.\nYour jian note, repeated facts, and stable constraints gradually become the context it can continue from later."
      },
      "skills": {
        "title": "Skills",
        "desc": "I can read/write files, run commands, and search the web. Manage more skills in Settings."
      },
      "workspace": {
        "title": "Workspace",
        "desc": "The default workspace lives at ~/Desktop/Lynn.\nIt is where you keep project files, references, and jian.md, and the first place Lynn checks during patrol."
      },
      "jian": {
        "title": "Jian",
        "desc": "jian.md is the main theme file for today's work.\nWrite what matters, what is blocked, and what should happen next there. Patrols and agents will read it first before deciding what to do."
      },
      "patrol": {
        "title": "Heartbeat / Patrol",
        "desc": "Heartbeat is Lynn coming back on a rhythm to re-check the workspace.\nIt rereads jian, notices project changes, and decides whether there is something it should continue on its own."
      },
      "activity": {
        "title": "Activity panel",
        "desc": "The activity panel shows what heartbeat saw, what background work ran, and what review follow-ups were triggered.\nSo when you come back later, you can resume immediately instead of asking what happened again."
      },
      "finish": "Let's Go",
      "quickFinish": "Enter Lynn now"
    },
    "skipSetup": "Skip setup"
  },
  "activity": {
    "title": "Activity",
    "empty": "No activity yet. Patrol runs and scheduled tasks will appear here.",
    "back": "Back",
    "openRecoveredTasks": "Open background tasks",
    "heartbeat": "Routine patrol",
    "plan": "Planning task",
    "delegate": "Delegated task",
    "reviewFollowUp": "Review follow-up",
    "cron": "Scheduled task",
    "patrolDone": "Patrol completed",
    "planDone": "Planning 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.",
    "guideTitle": "Automate with scheduled tasks",
    "guideDesc": "Set up tasks to run on a schedule. You can also ask the assistant to create them in chat.",
    "guideTip": "Click to add instantly. You can edit the time and content later.",
    "deleteConfirm": "Are you sure you want to delete this scheduled task?",
    "defaultModel": "Default model",
    "edit": "Edit",
    "delete": "Delete",
    "addCustom": "+ Custom Task",
    "customName": "Task name",
    "customPrompt": "Prompt",
    "customModel": "Model",
    "customDays": "Run on days",
    "customTime": "Run at time",
    "customSubmit": "Create task",
    "customCancel": "Cancel",
    "changeTime": "Change time",
    "tpl": {
      "newsLabel": "Daily Tech Digest",
      "newsDesc": "Search and summarize tech news every day at 9 AM",
      "diaryLabel": "Nightly Journal",
      "diaryDesc": "Write a journal entry every night at 10 PM",
      "repoLabel": "Weekday Project Check",
      "repoDesc": "Review Issues and PRs Monday through Friday",
      "cleanLabel": "Weekly Cleanup",
      "cleanDesc": "Clean up temp files every Sunday"
    }
  },
  "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...",
    "jianFooter": "Lynn reads this automatically during patrols · Markdown supported · ⌘J to toggle",
    "patrolIdle": "Opening Jian will trigger a patrol",
    "patrolRunning": "Lynn is reading this workspace and the plan in Jian",
    "patrolDone": "A patrol just finished",
    "patrolDoneAt": "Last patrol finished at {time}",
    "patrolError": "This patrol did not finish. Lynn will try again later",
    "automationIdle": "Recurring items in jian will automatically become automations",
    "automationReady": "{count} automations ready",
    "automationNext": "{count} automations set · next at {time}",
    "automationPausedSummary": "{count} automations set · {paused} paused",
    "automationNextWithPause": "{count} automations set · next at {time} · {paused} paused",
    "openDocBack": "Back to Jian",
    "openDocFooter": "Editing this document directly · Auto-saves to the original file",
    "openDocReadFailed": "Couldn't read this document",
    "openDocSaveFailed": "Failed to save document",
    "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.",
    "noDeskRoot": "Desk root is not set. Open Settings → Work and choose a folder.",
    "goToSettings": "Go to Settings",
    "fileLabel": "file",
    "openWithDefault": "Open with default app",
    "newFolder": "New Folder",
    "ctx": {
      "open": "Open",
      "openInLynn": "Open in Lynn",
      "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 for this turn to finish before sending another message.",
    "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)",
    "modelNoVision": "Current model does not support images. Please switch to a vision-capable model",
    "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}",
    "searchSynthesized": "📋 Synthesized answer:\n{summary}",
    "searchSources": "View sources ({count})",
    "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 Lynn'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",
    "settingsNoAgent": "No active agent, cannot modify this setting",
    "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}",
    "docxParseFailed": "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 Lynn",
      "settings": "Settings",
      "quit": "Quit"
    },
    "dialog": {
      "selectFolder": "Select Working Folder",
      "selectSkill": "Select Skill",
      "launchFailedTitle": "Lynn 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 the user explicitly asks for a preview page, HTML, long-form Markdown document, complete code file, or interactive visualization.\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, ordinary tables, simple calculations, management advice, 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"
    },
    "report": {
      "label": "Generate HTML Report",
      "description": "Only use this when the user explicitly asks for a report, HTML report, preview/export page, or publishable briefing. Generate a professional HTML report that can be previewed in chat, opened in a browser, and exported as PNG. Use for deep research, market analysis, industry reports, project retrospectives, and publishable briefings. Simple calculations, ordinary tables, summaries, and management advice should be answered directly in chat, not with this tool. Provide real content sections first; do not generate shell reports. stylePreset options: editorial-paper (paper-magazine deep report, recommended default), finance-dark (dark finance dashboard), magazine (bold magazine layout), clean-briefing (clean business briefing).",
      "titleDesc": "Report title",
      "tagDesc": "Report category or short tag, e.g. Equity Research, Industry Watch",
      "subtitleDesc": "Subtitle or one-sentence summary",
      "dateDesc": "Report date",
      "stylePresetDesc": "Visual style: editorial-paper for polished Claude-like deep HTML reports; finance-dark for market dashboards; magazine for publishable magazine/poster pages; clean-briefing for concise business briefs. If omitted, deep reports default to editorial-paper and regular reports default to finance-dark.",
      "secTitleDesc": "Section title",
      "secTypeDesc": "Section type: metrics cards, text body, table, verdict/scenarios, or warning/risk notes",
      "sectionsDesc": "Report sections. Deep reports need at least 3 substantive sections with data basis, analysis, and risk or scenario reasoning.",
      "disclaimerDesc": "Disclaimer or boundary note",
      "created": "Generated HTML report \"{title}\" with {count} sections, saved to {path}"
    },
    "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: ISO time (at), minutes (every, e.g. 60=hourly), 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 Lynn'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": "Legacy execution toggle",
      "sandboxDesc": "Compatibility-only setting; you usually do not need to change this",
      "securityMode": "Security Mode",
      "securityModeDesc": "Three-mode security policy (Execute/Plan/Safe)",
      "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 Lynn's current execution policy. This is not a bug; it is a protection mechanism at work. Please tell the user the action was blocked and explain why. They can switch execution mode or broaden the approval scope.",
    "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",
    "noDeleteFiles": "Deleting files requires confirmation",
    "noFindDelete": "find -delete requires confirmation",
    "noTrashFiles": "Moving files to Trash requires confirmation",
    "restrictedPath": "Command accessed a restricted path: {path}",
    "writeRestricted": "[Security] File system writes are currently limited to approved workspaces. This action was blocked. Ask the user to broaden approval or work inside the current workspace.",
    "osRequired": "[Protected execution environment] This execution boundary is not supported on the current platform ({platform}). Switch to Execute mode or continue on a supported platform.",
    "opRead": "Read",
    "opWrite": "Write",
    "opDelete": "Delete",
    "denied": "{op} denied: {path} (access level: {level})",
    "authDesc": {
      "sudo": "Run command with admin privileges — typically used for installing software or modifying system settings",
      "su": "Switch to another user identity — gain different user's permissions",
      "chmod": "Change file/directory permissions — control who can read, write, or execute these files",
      "chown": "Change file ownership — transfer file ownership to another user",
      "delRecursive": "Recursively delete files — will delete all files in the specified directory",
      "rmdirRecursive": "Recursively remove directory — will remove the entire directory tree, irreversible",
      "regEdit": "Modify Windows Registry — affects system and application configuration",
      "takeown": "Take file ownership — gain full control over the file",
      "icacls": "Modify file ACL — change file security permissions",
      "netUser": "Manage system users/groups — create, delete, or modify user accounts",
      "schtasks": "Create scheduled task — set up programs to run automatically on a schedule",
      "scService": "Manage system services — create or delete Windows services",
      "psBypass": "Bypass PowerShell execution policy — allow running unsigned scripts",
      "format": "Format disk — will erase ALL data on the disk, irreversible",
      "bcdedit": "Modify boot configuration — change how the system starts",
      "wmic": "Execute WMI management command — access and modify system management information",
      "deleteFiles": "Delete files or folders — confirm the matched scope, count, and target paths to avoid accidental deletion",
      "findDelete": "Batch-delete files matched by find — confirm the matched file list and count first",
      "trashFiles": "Move files to Trash — usually recoverable, but still changes the user's files",
      "pathOp": "{op} path {path} — this path is in a protected area"
    }
  },
  "security": {
    "mode": {
      "authorized": "Execute",
      "authorizedDesc": "Recommended default. Normal execution, with prompts for risky operations or protected paths",
      "plan": "Plan",
      "planDesc": "Analyze only, no execution",
      "safe": "Safe",
      "safeDesc": "Read-first mode. Risky operations are rejected directly",
      "fullAccess": "Full Access",
      "fullAccessDesc": "Run without restrictions (legacy compatibility wording)"
    },
    "auth": {
      "title": "This action needs your approval",
      "summary": "Lynn wants to perform a {scope} action in {project}. Choose how much to allow.",
      "reasonLabel": "Why this is needed",
      "commandLabel": "Command to run",
      "allow": "Allow",
      "allowOnce": "Allow just this step",
      "allowSession": "Allow for this task",
      "allowAlwaysHere": "Always allow in this project",
      "reject": "No, do not run it",
      "allowed": "Execution allowed",
      "rejected": "Rejected",
      "alwaysAllow": "Always allow this type of operation",
      "trustedRoot": "Trusted root",
      "scope": "Terminal",
      "fileWrite": "File write",
      "fileRead": "File read",
      "fileOp": "File access",
      "terminal": "Terminal action",
      "currentProject": "current project",
      "allowOnceHint": "Only allow this single action.",
      "allowSessionHint": "Allow similar actions for the rest of this task or session.",
      "allowAlwaysHereHint": "Always allow similar actions inside {project}."
    }
  },
  "error.llmTimeout": "Model request timed out",
  "error.llmRateLimited": "Model rate limited, please wait",
  "error.llmEmptyResponse": "Model returned empty response",
  "error.llmAuthFailed": "Model authentication failed — start a new conversation; if it persists, check your model/provider settings or system clock",
  "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",
  "status.tasksRecovered": "Recovered {count} background task(s)",
  "status.tasksRecoveredRunning": "{count} background task(s) are still running",
  "status.tasksRecoveredWaiting": "{count} background task(s) are still running, with {waiting} waiting for approval",
  "action.retry": "Retry",
  "agentDiscovery.title": "AI Tools Detected",
  "agentDiscovery.body": "Found installed AI tools on your device:",
  "agentDiscovery.benefit": "Once enabled, Lynn can reuse their skill libraries to boost capabilities — no extra setup needed.",
  "agentDiscovery.enable": "Enable",
  "agentDiscovery.later": "Later",
  "fleet": {
    "empty": {
      "title": "No parallel workers yet",
      "intro": "Split one task across 3-5 CLI workers (codex / claude / qwen ...), each in its own isolated git worktree, and supervise progress, diffs, and tests here.",
      "step1": "Dispatch worker — write a brief: which files it owns, which are forbidden, the test commands.",
      "step2": "Each worker runs in its own worktree; this board shows its live log, per-file diff, and tests.",
      "step3": "Out-of-scope edits and center-file conflicts are flagged red and block merge.",
      "step4": "Cancel / retry / open the worktree from each card.",
      "hint": "New here? Click \"Play mock worker\" to watch a simulated run end-to-end."
    },
    "dispatch": "Dispatch worker",
    "closeForm": "Close form",
    "playMock": "Play mock worker",
    "form": {
      "title": "Title",
      "titlePlaceholder": "e.g. Split ComposerTextarea",
      "agent": "Agent",
      "ready": "Ready",
      "taskType": "Task type",
      "taskTypeCode": "Code / text work",
      "taskTypeSee": "See image",
      "taskTypeGround": "Ground UI element",
      "taskTypeUi2code": "UI to code",
      "scopePreset": "Scope preset",
      "fanOut": "Fan out to (parallel, optional)",
      "imagePath": "Image path",
      "imageHint": "The path is passed to Lynn worker run; the CLI reads the image locally and routes it through a vision-capable model.",
      "approval": "Approval",
      "approvalAsk": "ask (guarded)",
      "approvalOnFailure": "on-failure",
      "approvalNever": "never (read/check only)",
      "approvalYolo": "yolo (autonomous edits)",
      "approvalHintYolo": "YOLO lets the worker edit files and run shell tools without another prompt.",
      "approvalHintGuarded": "Non-interactive workers may stop before dangerous edits unless approval is yolo.",
      "sandbox": "Sandbox",
      "sandboxHintFull": "Full filesystem access is only for trusted local worktrees.",
      "sandboxHintScoped": "Workspace-write keeps edits scoped to the assigned worktree.",
      "externalHint": "External CLI adapters run their own shell/process. To launch them from Fleet, explicitly set Approval=yolo and Sandbox=danger-full-access. Built-in Lynn and StepFun workers can stay guarded.",
      "branch": "Branch",
      "worktree": "Worktree",
      "objective": "Objective",
      "owned": "Owned files (one glob per line)",
      "forbidden": "Forbidden files",
      "tests": "Test commands (one per line)",
      "dispatching": "Dispatching...",
      "dispatchN": "Dispatch to {count} workers",
      "cancel": "Cancel",
      "unavailable": "unavailable"
    },
    "panel": {
      "cliRuntime": "CLI runtime",
      "perms": "perms",
      "workersCount": "{count} worker(s)",
      "mockBadge": "mock",
      "mockBadgeTitle": "Demo playback — no real process was launched"
    },
    "chatHint": {
      "text": "⚡ This task looks splittable across parallel workers",
      "action": "Dispatch"
    },
    "acceptance": {
      "passed": "✓ Acceptance passed",
      "failed": "✗ Acceptance failed",
      "falseVerify": "false-verify risk",
      "evidence": "evidence",
      "escalated": "escalated"
    }
  },
  "jarvis": {
    "ariaLabel": "Lynn voice assistant",
    "action": {
      "start": "Realtime voice",
      "endTurn": "Finish turn",
      "interruptListen": "Talk over",
      "interrupt": "Stop"
    },
    "state": {
      "idle": "Tap once for continuous voice",
      "listening": "Listening · finish turn when done",
      "thinking": "Thinking",
      "speaking": "Speaking the answer",
      "degraded": "Voice service issue"
    },
    "hint": {
      "idle": "Tap once for continuous voice. Lynn resumes listening after playback; stop or close to exit.",
      "listening": "Listening now. In noisy rooms, tap Finish turn after speaking.",
      "thinking": "Preparing the answer; playback starts automatically.",
      "speaking": "Playing the answer. Lynn resumes listening after playback; use Talk over to interrupt."
    }
  }
}
