diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index af9c7530f..ac5beed69 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -48,7 +48,7 @@ import { type PromptHistoryStoredEntry, promptLength, } from "./prompt-input/history" -import { createPromptSubmit } from "./prompt-input/submit" +import { createPromptSubmit, type FollowupDraft } from "./prompt-input/submit" import { PromptPopover, type AtOption, type SlashCommand } from "./prompt-input/slash-popover" import { PromptContextItems } from "./prompt-input/context-items" import { PromptImageAttachments } from "./prompt-input/image-attachments" @@ -61,6 +61,11 @@ interface PromptInputProps { ref?: (el: HTMLDivElement) => void newSessionWorktree?: string onNewSessionWorktreeReset?: () => void + edit?: { id: string; prompt: Prompt; context: FollowupDraft["context"] } + onEditLoaded?: () => void + shouldQueue?: () => boolean + onQueue?: (draft: FollowupDraft) => void + onAbort?: () => void onSubmit?: () => void } @@ -947,6 +952,45 @@ export const PromptInput: Component = (props) => { setCurrentHistory("entries", next) } + createEffect( + on( + () => props.edit?.id, + (id) => { + const edit = props.edit + if (!id || !edit) return + + for (const item of prompt.context.items()) { + prompt.context.remove(item.key) + } + + for (const item of edit.context) { + prompt.context.add({ + type: item.type, + path: item.path, + selection: item.selection, + comment: item.comment, + commentID: item.commentID, + commentOrigin: item.commentOrigin, + preview: item.preview, + }) + } + + setStore("mode", "normal") + setStore("popover", null) + setStore("historyIndex", -1) + setStore("savedPrompt", null) + prompt.set(edit.prompt, promptLength(edit.prompt)) + requestAnimationFrame(() => { + editorRef.focus() + setCursorPosition(editorRef, promptLength(edit.prompt)) + queueScroll() + }) + props.onEditLoaded?.() + }, + { defer: true }, + ), + ) + const navigateHistory = (direction: "up" | "down") => { const result = navigatePromptHistory({ direction, @@ -1001,6 +1045,9 @@ export const PromptInput: Component = (props) => { setPopover: (popover) => setStore("popover", popover), newSessionWorktree: () => props.newSessionWorktree, onNewSessionWorktreeReset: props.onNewSessionWorktreeReset, + shouldQueue: props.shouldQueue, + onQueue: props.onQueue, + onAbort: props.onAbort, onSubmit: props.onSubmit, }) diff --git a/packages/app/src/components/prompt-input/submit.ts b/packages/app/src/components/prompt-input/submit.ts index fee6b070d..eb3e0c82f 100644 --- a/packages/app/src/components/prompt-input/submit.ts +++ b/packages/app/src/components/prompt-input/submit.ts @@ -9,7 +9,7 @@ import { useLanguage } from "@/context/language" import { useLayout } from "@/context/layout" import { useLocal } from "@/context/local" import { usePermission } from "@/context/permission" -import { type ImageAttachmentPart, type Prompt, usePrompt } from "@/context/prompt" +import { type ContextItem, type ImageAttachmentPart, type Prompt, usePrompt } from "@/context/prompt" import { useSDK } from "@/context/sdk" import { useSync } from "@/context/sync" import { Identifier } from "@/utils/id" @@ -25,6 +25,145 @@ type PendingPrompt = { const pending = new Map() +export type FollowupDraft = { + sessionID: string + sessionDirectory: string + prompt: Prompt + context: (ContextItem & { key: string })[] + agent: string + model: { providerID: string; modelID: string } + variant?: string +} + +type FollowupSendInput = { + client: ReturnType["client"] + globalSync: ReturnType + sync: ReturnType + draft: FollowupDraft + messageID?: string + optimisticBusy?: boolean + before?: () => Promise | boolean +} + +const draftText = (prompt: Prompt) => prompt.map((part) => ("content" in part ? part.content : "")).join("") + +const draftImages = (prompt: Prompt) => prompt.filter((part): part is ImageAttachmentPart => part.type === "image") + +export async function sendFollowupDraft(input: FollowupSendInput) { + const text = draftText(input.draft.prompt) + const images = draftImages(input.draft.prompt) + const [, setStore] = input.globalSync.child(input.draft.sessionDirectory) + + const setBusy = () => { + if (!input.optimisticBusy) return + setStore("session_status", input.draft.sessionID, { type: "busy" }) + } + + const setIdle = () => { + if (!input.optimisticBusy) return + setStore("session_status", input.draft.sessionID, { type: "idle" }) + } + + const wait = async () => { + const ok = await input.before?.() + if (ok === false) return false + return true + } + + const [head, ...tail] = text.split(" ") + const cmd = head?.startsWith("/") ? head.slice(1) : undefined + if (cmd && input.sync.data.command.find((item) => item.name === cmd)) { + setBusy() + try { + if (!(await wait())) { + setIdle() + return false + } + + await input.client.session.command({ + sessionID: input.draft.sessionID, + command: cmd, + arguments: tail.join(" "), + agent: input.draft.agent, + model: `${input.draft.model.providerID}/${input.draft.model.modelID}`, + variant: input.draft.variant, + parts: images.map((attachment) => ({ + id: Identifier.ascending("part"), + type: "file" as const, + mime: attachment.mime, + url: attachment.dataUrl, + filename: attachment.filename, + })), + }) + return true + } catch (err) { + setIdle() + throw err + } + } + + const messageID = input.messageID ?? Identifier.ascending("message") + const { requestParts, optimisticParts } = buildRequestParts({ + prompt: input.draft.prompt, + context: input.draft.context, + images, + text, + sessionID: input.draft.sessionID, + messageID, + sessionDirectory: input.draft.sessionDirectory, + }) + + const message: Message = { + id: messageID, + sessionID: input.draft.sessionID, + role: "user", + time: { created: Date.now() }, + agent: input.draft.agent, + model: input.draft.model, + variant: input.draft.variant, + } + + const add = () => + input.sync.session.optimistic.add({ + directory: input.draft.sessionDirectory, + sessionID: input.draft.sessionID, + message, + parts: optimisticParts, + }) + + const remove = () => + input.sync.session.optimistic.remove({ + directory: input.draft.sessionDirectory, + sessionID: input.draft.sessionID, + messageID, + }) + + setBusy() + add() + + try { + if (!(await wait())) { + setIdle() + remove() + return false + } + + await input.client.session.promptAsync({ + sessionID: input.draft.sessionID, + agent: input.draft.agent, + model: input.draft.model, + messageID, + parts: requestParts, + variant: input.draft.variant, + }) + return true + } catch (err) { + setIdle() + remove() + throw err + } +} + type PromptSubmitInput = { info: Accessor<{ id: string } | undefined> imageAttachments: Accessor @@ -41,6 +180,9 @@ type PromptSubmitInput = { setPopover: (popover: "at" | "slash" | null) => void newSessionWorktree?: Accessor onNewSessionWorktreeReset?: () => void + shouldQueue?: Accessor + onQueue?: (draft: FollowupDraft) => void + onAbort?: () => void onSubmit?: () => void } @@ -82,6 +224,8 @@ export function createPromptSubmit(input: PromptSubmitInput) { const [, setStore] = globalSync.child(sdk.directory) setStore("todo", sessionID, []) + input.onAbort?.() + const queued = pending.get(sessionID) if (queued) { queued.abort.abort() @@ -116,6 +260,12 @@ export function createPromptSubmit(input: PromptSubmitInput) { } } + const clearContext = () => { + for (const item of prompt.context.items()) { + prompt.context.remove(item.key) + } + } + const handleSubmit = async (event: Event) => { event.preventDefault() @@ -215,14 +365,22 @@ export function createPromptSubmit(input: PromptSubmitInput) { return } - input.onSubmit?.() - const model = { modelID: currentModel.id, providerID: currentModel.provider.id, } const agent = currentAgent.name const variant = local.model.variant.current() + const context = prompt.context.items().slice() + const draft: FollowupDraft = { + sessionID: session.id, + sessionDirectory, + prompt: currentPrompt, + context, + agent, + model, + variant, + } const clearInput = () => { prompt.reset() @@ -243,6 +401,15 @@ export function createPromptSubmit(input: PromptSubmitInput) { }) } + if (!isNewSession && mode === "normal" && input.shouldQueue?.()) { + input.onQueue?.(draft) + clearContext() + clearInput() + return + } + + input.onSubmit?.() + if (mode === "shell") { clearInput() client.session @@ -295,48 +462,19 @@ export function createPromptSubmit(input: PromptSubmitInput) { } } - const context = prompt.context.items().slice() const commentItems = context.filter((item) => item.type === "file" && !!item.comment?.trim()) - const messageID = Identifier.ascending("message") - const { requestParts, optimisticParts } = buildRequestParts({ - prompt: currentPrompt, - context, - images, - text, - sessionID: session.id, - messageID, - sessionDirectory, - }) - const optimisticMessage: Message = { - id: messageID, - sessionID: session.id, - role: "user", - time: { created: Date.now() }, - agent, - model, - variant, - } - - const addOptimisticMessage = () => - sync.session.optimistic.add({ - directory: sessionDirectory, - sessionID: session.id, - message: optimisticMessage, - parts: optimisticParts, - }) - - const removeOptimisticMessage = () => + const removeOptimisticMessage = () => { sync.session.optimistic.remove({ directory: sessionDirectory, sessionID: session.id, messageID, }) + } removeCommentItems(commentItems) clearInput() - addOptimisticMessage() const waitForWorktree = async () => { const worktree = WorktreeState.get(sessionDirectory) @@ -393,20 +531,15 @@ export function createPromptSubmit(input: PromptSubmitInput) { return true } - const send = async () => { - const ok = await waitForWorktree() - if (!ok) return - await client.session.promptAsync({ - sessionID: session.id, - agent, - model, - messageID, - parts: requestParts, - variant, - }) - } - - void send().catch((err) => { + void sendFollowupDraft({ + client, + sync, + globalSync, + draft, + messageID, + optimisticBusy: sessionDirectory === projectDirectory, + before: waitForWorktree, + }).catch((err) => { pending.delete(session.id) if (sessionDirectory === projectDirectory) { sync.set("session_status", session.id, { type: "idle" }) diff --git a/packages/app/src/components/settings-general.tsx b/packages/app/src/components/settings-general.tsx index 42ee4092f..16689bfe2 100644 --- a/packages/app/src/components/settings-general.tsx +++ b/packages/app/src/components/settings-general.tsx @@ -113,6 +113,11 @@ export const SettingsGeneral: Component = () => { { value: "dark", label: language.t("theme.scheme.dark") }, ]) + const followupOptions = createMemo((): { value: "queue" | "steer"; label: string }[] => [ + { value: "queue", label: language.t("settings.general.row.followup.option.queue") }, + { value: "steer", label: language.t("settings.general.row.followup.option.steer") }, + ]) + const languageOptions = createMemo(() => language.locales.map((locale) => ({ value: locale, @@ -170,10 +175,8 @@ export const SettingsGeneral: Component = () => { triggerVariant: "settings" as const, }) - const AppearanceSection = () => ( + const GeneralSection = () => (
-

{language.t("settings.general.section.appearance")}

-
{ +
+ settings.general.setShowReasoningSummaries(checked)} + /> +
+
+ + +
+ settings.general.setShellToolPartsExpanded(checked)} + /> +
+
+ + +
+ settings.general.setEditToolPartsExpanded(checked)} + /> +
+
+ + + { variant="secondary" size="small" triggerVariant="settings" + triggerStyle={{ "min-width": "220px" }} /> @@ -271,50 +337,6 @@ export const SettingsGeneral: Component = () => {
) - const FeedSection = () => ( -
-

{language.t("settings.general.section.feed")}

- -
- -
- settings.general.setShowReasoningSummaries(checked)} - /> -
-
- - -
- settings.general.setShellToolPartsExpanded(checked)} - /> -
-
- - -
- settings.general.setEditToolPartsExpanded(checked)} - /> -
-
-
-
- ) - const NotificationsSection = () => (

{language.t("settings.general.section.notifications")}

@@ -465,9 +487,9 @@ export const SettingsGeneral: Component = () => {
- + - + @@ -551,12 +573,12 @@ interface SettingsRowProps { const SettingsRow: Component = (props) => { return ( -
-
+
+
{props.title} {props.description}
-
{props.children}
+
{props.children}
) } diff --git a/packages/app/src/context/settings.tsx b/packages/app/src/context/settings.tsx index b43469b5c..48788fe8e 100644 --- a/packages/app/src/context/settings.tsx +++ b/packages/app/src/context/settings.tsx @@ -22,6 +22,7 @@ export interface Settings { general: { autoSave: boolean releaseNotes: boolean + followup: "queue" | "steer" showReasoningSummaries: boolean shellToolPartsExpanded: boolean editToolPartsExpanded: boolean @@ -45,6 +46,7 @@ const defaultSettings: Settings = { general: { autoSave: true, releaseNotes: true, + followup: "steer", showReasoningSummaries: false, shellToolPartsExpanded: true, editToolPartsExpanded: false, @@ -126,6 +128,10 @@ export const { use: useSettings, provider: SettingsProvider } = createSimpleCont setReleaseNotes(value: boolean) { setStore("general", "releaseNotes", value) }, + followup: withFallback(() => store.general?.followup, defaultSettings.general.followup), + setFollowup(value: "queue" | "steer") { + setStore("general", "followup", value) + }, showReasoningSummaries: withFallback( () => store.general?.showReasoningSummaries, defaultSettings.general.showReasoningSummaries, diff --git a/packages/app/src/i18n/ar.ts b/packages/app/src/i18n/ar.ts index c9b92db50..1b8720826 100644 --- a/packages/app/src/i18n/ar.ts +++ b/packages/app/src/i18n/ar.ts @@ -104,6 +104,7 @@ export const dict = { "dialog.model.empty": "لا توجد نتائج للنماذج", "dialog.model.manage": "إدارة النماذج", "dialog.model.manage.description": "تخصيص النماذج التي تظهر في محدد النماذج.", + "dialog.model.manage.provider.toggle": "تبديل جميع نماذج {{provider}}", "dialog.model.unpaid.freeModels.title": "نماذج مجانية مقدمة من OpenCode", "dialog.model.unpaid.addMore.title": "إضافة المزيد من النماذج من موفرين مشهورين", "dialog.provider.viewAll": "عرض المزيد من الموفرين", @@ -288,6 +289,11 @@ export const dict = { "dialog.server.add.error": "تعذر الاتصال بالخادم", "dialog.server.add.checking": "جارٍ التحقق...", "dialog.server.add.button": "إضافة خادم", + "dialog.server.add.name": "اسم الخادم (اختياري)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "اسم المستخدم (اختياري)", + "dialog.server.add.password": "كلمة المرور (اختياري)", + "dialog.server.edit.title": "تحرير الخادم", "dialog.server.default.title": "الخادم الافتراضي", "dialog.server.default.description": "الاتصال بهذا الخادم عند بدء تشغيل التطبيق بدلاً من بدء خادم محلي. يتطلب إعادة التشغيل.", @@ -358,6 +364,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "لغة", "toast.language.description": "تم التبديل إلى {{language}}", "toast.theme.title": "تم تبديل السمة", @@ -444,8 +451,11 @@ export const dict = { "session.review.loadingChanges": "جارٍ تحميل التغييرات...", "session.review.empty": "لا توجد تغييرات في هذه الجلسة بعد", "session.review.noChanges": "لا توجد تغييرات", + "session.review.noVcs": "لم يتم اكتشاف نظام التحكم في الإصدار Git، لن يتم عرض التغييرات", + "session.review.noSnapshot": "تم تعطيل تتبع اللقطات في التكوين، لذا فإن تغييرات الجلسة غير متوفرة", "session.files.selectToOpen": "اختر ملفًا لفتحه", "session.files.all": "كل الملفات", + "session.files.empty": "لا توجد ملفات", "session.files.binaryContent": "ملف ثنائي (لا يمكن عرض المحتوى)", "session.messages.renderEarlier": "عرض الرسائل السابقة", "session.messages.loadingEarlier": "جارٍ تحميل الرسائل السابقة...", @@ -456,6 +466,17 @@ export const dict = { "session.todo.title": "المهام", "session.todo.collapse": "طي", "session.todo.expand": "توسيع", + "session.followupDock.summary.one": "{{count}} رسالة في الانتظار", + "session.followupDock.summary.other": "{{count}} رسائل في الانتظار", + "session.followupDock.sendNow": "إرسال الآن", + "session.followupDock.edit": "تحرير", + "session.followupDock.collapse": "طي الرسائل المنتظرة", + "session.followupDock.expand": "توسيع الرسائل المنتظرة", + "session.revertDock.summary.one": "{{count}} رسالة تم التراجع عنها", + "session.revertDock.summary.other": "{{count}} رسائل تم التراجع عنها", + "session.revertDock.collapse": "طي الرسائل التي تم التراجع عنها", + "session.revertDock.expand": "توسيع الرسائل التي تم التراجع عنها", + "session.revertDock.restore": "استعادة الرسالة", "session.new.title": "ابنِ أي شيء", "session.new.worktree.main": "الفرع الرئيسي", "session.new.worktree.mainWithBranch": "الفرع الرئيسي ({{branch}})", @@ -538,10 +559,18 @@ export const dict = { "settings.general.row.language.description": "تغيير لغة العرض لـ OpenCode", "settings.general.row.appearance.title": "المظهر", "settings.general.row.appearance.description": "تخصيص كيفية ظهور OpenCode على جهازك", + "settings.general.row.colorScheme.title": "مخطط الألوان", + "settings.general.row.colorScheme.description": "اختر ما إذا كان OpenCode يتبع سمة النظام أو الفاتح أو الداكن", "settings.general.row.theme.title": "السمة", "settings.general.row.theme.description": "تخصيص سمة OpenCode.", "settings.general.row.font.title": "الخط", "settings.general.row.font.description": "تخصيص الخط الأحادي المستخدم في كتل التعليمات البرمجية", + "settings.general.row.followup.title": "سلوك المتابعة", + "settings.general.row.followup.description": "اختر ما إذا كانت طلبات المتابعة توجه فورًا أو تنتظر في قائمة انتظار", + "settings.general.row.followup.option.queue": "قائمة انتظار", + "settings.general.row.followup.option.steer": "توجيه", + "settings.general.row.reasoningSummaries.title": "إظهار ملخصات الاستنتاج", + "settings.general.row.reasoningSummaries.description": "عرض ملخصات استنتاج النموذج في الشريط الزمني", "settings.general.row.shellToolPartsExpanded.title": "توسيع أجزاء أداة shell", "settings.general.row.shellToolPartsExpanded.description": "إظهار أجزاء أداة shell موسعة بشكل افتراضي في الشريط الزمني", diff --git a/packages/app/src/i18n/br.ts b/packages/app/src/i18n/br.ts index 951edf0a5..9e1f7f2a0 100644 --- a/packages/app/src/i18n/br.ts +++ b/packages/app/src/i18n/br.ts @@ -104,6 +104,7 @@ export const dict = { "dialog.model.empty": "Nenhum resultado de modelo", "dialog.model.manage": "Gerenciar modelos", "dialog.model.manage.description": "Personalizar quais modelos aparecem no seletor de modelos.", + "dialog.model.manage.provider.toggle": "Alternar todos os modelos {{provider}}", "dialog.model.unpaid.freeModels.title": "Modelos gratuitos fornecidos pelo OpenCode", "dialog.model.unpaid.addMore.title": "Adicionar mais modelos de provedores populares", "dialog.provider.viewAll": "Ver mais provedores", @@ -288,6 +289,11 @@ export const dict = { "dialog.server.add.error": "Não foi possível conectar ao servidor", "dialog.server.add.checking": "Verificando...", "dialog.server.add.button": "Adicionar", + "dialog.server.add.name": "Nome do servidor (opcional)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Nome de usuário (opcional)", + "dialog.server.add.password": "Senha (opcional)", + "dialog.server.edit.title": "Editar servidor", "dialog.server.default.title": "Servidor padrão", "dialog.server.default.description": "Conectar a este servidor na inicialização do aplicativo ao invés de iniciar um servidor local. Requer reinicialização.", @@ -359,6 +365,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Idioma", "toast.language.description": "Alterado para {{language}}", "toast.theme.title": "Tema alterado", @@ -446,9 +453,13 @@ export const dict = { "session.review.change.other": "Alterações", "session.review.loadingChanges": "Carregando alterações...", "session.review.empty": "Nenhuma alteração nesta sessão ainda", + "session.review.noVcs": "Nenhum Sistema de Controle de Versão Git detectado, alterações não exibidas", + "session.review.noSnapshot": + "O rastreamento de snapshot está desabilitado na configuração, então as alterações da sessão estão indisponíveis", "session.review.noChanges": "Sem alterações", "session.files.selectToOpen": "Selecione um arquivo para abrir", "session.files.all": "Todos os arquivos", + "session.files.empty": "Nenhum arquivo", "session.files.binaryContent": "Arquivo binário (conteúdo não pode ser exibido)", "session.messages.renderEarlier": "Renderizar mensagens anteriores", "session.messages.loadingEarlier": "Carregando mensagens anteriores...", @@ -459,6 +470,17 @@ export const dict = { "session.todo.title": "Tarefas", "session.todo.collapse": "Recolher", "session.todo.expand": "Expandir", + "session.followupDock.summary.one": "{{count}} mensagem na fila", + "session.followupDock.summary.other": "{{count}} mensagens na fila", + "session.followupDock.sendNow": "Enviar agora", + "session.followupDock.edit": "Editar", + "session.followupDock.collapse": "Recolher mensagens na fila", + "session.followupDock.expand": "Expandir mensagens na fila", + "session.revertDock.summary.one": "{{count}} mensagem revertida", + "session.revertDock.summary.other": "{{count}} mensagens revertidas", + "session.revertDock.collapse": "Recolher mensagens revertidas", + "session.revertDock.expand": "Expandir mensagens revertidas", + "session.revertDock.restore": "Restaurar mensagem", "session.new.title": "Crie qualquer coisa", "session.new.worktree.main": "Branch principal", "session.new.worktree.mainWithBranch": "Branch principal ({{branch}})", @@ -544,10 +566,19 @@ export const dict = { "settings.general.row.language.description": "Alterar o idioma de exibição do OpenCode", "settings.general.row.appearance.title": "Aparência", "settings.general.row.appearance.description": "Personalize como o OpenCode aparece no seu dispositivo", + "settings.general.row.colorScheme.title": "Esquema de cores", + "settings.general.row.colorScheme.description": "Escolha se o OpenCode segue o tema do sistema, claro ou escuro", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "Personalize como o OpenCode é tematizado.", "settings.general.row.font.title": "Fonte", "settings.general.row.font.description": "Personalize a fonte monoespaçada usada em blocos de código", + "settings.general.row.followup.title": "Comportamento de acompanhamento", + "settings.general.row.followup.description": + "Escolha se os prompts de acompanhamento orientam imediatamente ou esperam na fila", + "settings.general.row.followup.option.queue": "Fila", + "settings.general.row.followup.option.steer": "Orientar", + "settings.general.row.reasoningSummaries.title": "Mostrar resumos de raciocínio", + "settings.general.row.reasoningSummaries.description": "Exibir resumos de raciocínio do modelo na linha do tempo", "settings.general.row.shellToolPartsExpanded.title": "Expandir partes da ferramenta shell", "settings.general.row.shellToolPartsExpanded.description": "Mostrar partes da ferramenta shell expandidas por padrão na linha do tempo", diff --git a/packages/app/src/i18n/bs.ts b/packages/app/src/i18n/bs.ts index e8bdcde59..3151c9b22 100644 --- a/packages/app/src/i18n/bs.ts +++ b/packages/app/src/i18n/bs.ts @@ -113,6 +113,7 @@ export const dict = { "dialog.model.empty": "Nema rezultata za modele", "dialog.model.manage": "Upravljaj modelima", "dialog.model.manage.description": "Prilagodi koji se modeli prikazuju u izborniku modela.", + "dialog.model.manage.provider.toggle": "Uključi/isključi sve {{provider}} modele", "dialog.model.unpaid.freeModels.title": "Besplatni modeli koje obezbjeđuje OpenCode", "dialog.model.unpaid.addMore.title": "Dodaj još modela od popularnih provajdera", @@ -315,6 +316,11 @@ export const dict = { "dialog.server.add.error": "Nije moguće povezati se na server", "dialog.server.add.checking": "Provjera...", "dialog.server.add.button": "Dodaj server", + "dialog.server.add.name": "Ime servera (opcionalno)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Korisničko ime (opcionalno)", + "dialog.server.add.password": "Lozinka (opcionalno)", + "dialog.server.edit.title": "Uredi server", "dialog.server.default.title": "Podrazumijevani server", "dialog.server.default.description": "Poveži se na ovaj server pri pokretanju aplikacije umjesto pokretanja lokalnog servera. Potreban je restart.", @@ -393,6 +399,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Jezik", "toast.language.description": "Prebačeno na {{language}}", @@ -498,10 +505,14 @@ export const dict = { "session.review.change.other": "Izmjene", "session.review.loadingChanges": "Učitavanje izmjena...", "session.review.empty": "Još nema izmjena u ovoj sesiji", + "session.review.noVcs": "Nije detektovan Git sistem kontrole verzija, promjene se ne prikazuju", + "session.review.noSnapshot": + "Praćenje snimaka (snapshot) je onemogućeno u konfiguraciji, pa promjene sesije nisu dostupne", "session.review.noChanges": "Nema izmjena", "session.files.selectToOpen": "Odaberi datoteku za otvaranje", "session.files.all": "Sve datoteke", + "session.files.empty": "Nema datoteka", "session.files.binaryContent": "Binarna datoteka (sadržaj se ne može prikazati)", "session.messages.renderEarlier": "Prikaži ranije poruke", @@ -514,6 +525,17 @@ export const dict = { "session.todo.title": "Zadaci", "session.todo.collapse": "Sažmi", "session.todo.expand": "Proširi", + "session.followupDock.summary.one": "{{count}} poruka na čekanju", + "session.followupDock.summary.other": "{{count}} poruka na čekanju", + "session.followupDock.sendNow": "Pošalji sada", + "session.followupDock.edit": "Uredi", + "session.followupDock.collapse": "Sažmi poruke na čekanju", + "session.followupDock.expand": "Proširi poruke na čekanju", + "session.revertDock.summary.one": "{{count}} vraćena poruka", + "session.revertDock.summary.other": "{{count}} vraćenih poruka", + "session.revertDock.collapse": "Sažmi vraćene poruke", + "session.revertDock.expand": "Proširi vraćene poruke", + "session.revertDock.restore": "Vrati poruku", "session.new.title": "Napravi bilo šta", "session.new.worktree.main": "Glavna grana", @@ -609,10 +631,18 @@ export const dict = { "settings.general.row.language.description": "Promijeni jezik prikaza u OpenCode-u", "settings.general.row.appearance.title": "Izgled", "settings.general.row.appearance.description": "Prilagodi kako OpenCode izgleda na tvom uređaju", + "settings.general.row.colorScheme.title": "Šema boja", + "settings.general.row.colorScheme.description": "Odaberi da li OpenCode prati sistemsku, svijetlu ili tamnu temu", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "Prilagodi temu OpenCode-a.", "settings.general.row.font.title": "Font", "settings.general.row.font.description": "Prilagodi monospace font koji se koristi u blokovima koda", + "settings.general.row.followup.title": "Ponašanje nadovezivanja", + "settings.general.row.followup.description": "Odaberi da li upiti nadovezivanja usmjeravaju odmah ili čekaju u redu", + "settings.general.row.followup.option.queue": "Red čekanja", + "settings.general.row.followup.option.steer": "Usmjeri", + "settings.general.row.reasoningSummaries.title": "Prikaži sažetke rasuđivanja", + "settings.general.row.reasoningSummaries.description": "Prikaži sažetke rasuđivanja modela na vremenskoj traci", "settings.general.row.shellToolPartsExpanded.title": "Proširi dijelove shell alata", "settings.general.row.shellToolPartsExpanded.description": diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts index 5ea52a5c9..8d9331ab6 100644 --- a/packages/app/src/i18n/da.ts +++ b/packages/app/src/i18n/da.ts @@ -113,6 +113,7 @@ export const dict = { "dialog.model.empty": "Ingen modeller fundet", "dialog.model.manage": "Administrer modeller", "dialog.model.manage.description": "Tilpas hvilke modeller der vises i modelvælgeren.", + "dialog.model.manage.provider.toggle": "Skift alle {{provider}}-modeller", "dialog.model.unpaid.freeModels.title": "Gratis modeller leveret af OpenCode", "dialog.model.unpaid.addMore.title": "Tilføj flere modeller fra populære udbydere", @@ -313,6 +314,11 @@ export const dict = { "dialog.server.add.error": "Kunne ikke forbinde til server", "dialog.server.add.checking": "Tjekker...", "dialog.server.add.button": "Tilføj server", + "dialog.server.add.name": "Servernavn (valgfrit)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Brugernavn (valgfrit)", + "dialog.server.add.password": "Adgangskode (valgfrit)", + "dialog.server.edit.title": "Rediger server", "dialog.server.default.title": "Standardserver", "dialog.server.default.description": "Forbind til denne server ved start af app i stedet for at starte en lokal server. Kræver genstart.", @@ -391,6 +397,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Sprog", "toast.language.description": "Skiftede til {{language}}", @@ -495,9 +502,13 @@ export const dict = { "session.review.change.other": "Ændringer", "session.review.loadingChanges": "Indlæser ændringer...", "session.review.empty": "Ingen ændringer i denne session endnu", + "session.review.noVcs": "Intet Git versionsstyringssystem fundet, ændringer vises ikke", + "session.review.noSnapshot": + "Snapshot-sporing er deaktiveret i konfigurationen, så sessionsændringer er ikke tilgængelige", "session.review.noChanges": "Ingen ændringer", "session.files.selectToOpen": "Vælg en fil at åbne", "session.files.all": "Alle filer", + "session.files.empty": "Ingen filer", "session.files.binaryContent": "Binær fil (indhold kan ikke vises)", "session.messages.renderEarlier": "Vis tidligere beskeder", "session.messages.loadingEarlier": "Indlæser tidligere beskeder...", @@ -509,6 +520,17 @@ export const dict = { "session.todo.title": "Opgaver", "session.todo.collapse": "Skjul", "session.todo.expand": "Udvid", + "session.followupDock.summary.one": "{{count}} besked i kø", + "session.followupDock.summary.other": "{{count}} beskeder i kø", + "session.followupDock.sendNow": "Send nu", + "session.followupDock.edit": "Rediger", + "session.followupDock.collapse": "Skjul beskeder i kø", + "session.followupDock.expand": "Udvid beskeder i kø", + "session.revertDock.summary.one": "{{count}} tilbagerullet besked", + "session.revertDock.summary.other": "{{count}} tilbagerullede beskeder", + "session.revertDock.collapse": "Skjul tilbagerullede beskeder", + "session.revertDock.expand": "Udvid tilbagerullede beskeder", + "session.revertDock.restore": "Gendan besked", "session.new.title": "Byg hvad som helst", "session.new.worktree.main": "Hovedgren", @@ -604,10 +626,18 @@ export const dict = { "settings.general.row.language.description": "Ændr visningssproget for OpenCode", "settings.general.row.appearance.title": "Udseende", "settings.general.row.appearance.description": "Tilpas hvordan OpenCode ser ud på din enhed", + "settings.general.row.colorScheme.title": "Farveskema", + "settings.general.row.colorScheme.description": "Vælg om OpenCode følger systemets, lyst eller mørkt tema", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "Tilpas hvordan OpenCode er temabestemt.", "settings.general.row.font.title": "Skrifttype", "settings.general.row.font.description": "Tilpas mono-skrifttypen brugt i kodeblokke", + "settings.general.row.followup.title": "Opfølgningsadfærd", + "settings.general.row.followup.description": "Vælg om opfølgende forespørgsler skal styre straks eller vente i kø", + "settings.general.row.followup.option.queue": "Kø", + "settings.general.row.followup.option.steer": "Styr", + "settings.general.row.reasoningSummaries.title": "Vis tænkeoversigter", + "settings.general.row.reasoningSummaries.description": "Vis model tænkeoversigter i tidslinjen", "settings.general.row.shellToolPartsExpanded.title": "Udvid shell-værktøjsdele", "settings.general.row.shellToolPartsExpanded.description": "Vis shell-værktøjsdele udvidet som standard i tidslinjen", diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts index a6cf8045c..782b67262 100644 --- a/packages/app/src/i18n/de.ts +++ b/packages/app/src/i18n/de.ts @@ -108,6 +108,7 @@ export const dict = { "dialog.model.empty": "Keine Modellergebnisse", "dialog.model.manage": "Modelle verwalten", "dialog.model.manage.description": "Anpassen, welche Modelle in der Modellauswahl erscheinen.", + "dialog.model.manage.provider.toggle": "Alle {{provider}}-Modelle umschalten", "dialog.model.unpaid.freeModels.title": "Kostenlose Modelle von OpenCode", "dialog.model.unpaid.addMore.title": "Weitere Modelle von beliebten Anbietern hinzufügen", "dialog.provider.viewAll": "Mehr Anbieter anzeigen", @@ -294,6 +295,11 @@ export const dict = { "dialog.server.add.error": "Verbindung zum Server fehlgeschlagen", "dialog.server.add.checking": "Prüfen...", "dialog.server.add.button": "Server hinzufügen", + "dialog.server.add.name": "Servername (optional)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Benutzername (optional)", + "dialog.server.add.password": "Passwort (optional)", + "dialog.server.edit.title": "Server bearbeiten", "dialog.server.default.title": "Standardserver", "dialog.server.default.description": "Beim App-Start mit diesem Server verbinden, anstatt einen lokalen Server zu starten. Erfordert Neustart.", @@ -366,6 +372,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Sprache", "toast.language.description": "Zu {{language}} gewechselt", "toast.theme.title": "Thema gewechselt", @@ -454,9 +461,13 @@ export const dict = { "session.review.change.other": "Änderungen", "session.review.loadingChanges": "Lade Änderungen...", "session.review.empty": "Noch keine Änderungen in dieser Sitzung", + "session.review.noVcs": "Kein Git-Versionskontrollsystem erkannt, Änderungen werden nicht angezeigt", + "session.review.noSnapshot": + "Snapshot-Tracking ist in der Konfiguration deaktiviert, daher sind Sitzungsänderungen nicht verfügbar", "session.review.noChanges": "Keine Änderungen", "session.files.selectToOpen": "Datei zum Öffnen auswählen", "session.files.all": "Alle Dateien", + "session.files.empty": "Keine Dateien", "session.files.binaryContent": "Binärdatei (Inhalt kann nicht angezeigt werden)", "session.messages.renderEarlier": "Frühere Nachrichten rendern", "session.messages.loadingEarlier": "Lade frühere Nachrichten...", @@ -467,6 +478,17 @@ export const dict = { "session.todo.title": "Aufgaben", "session.todo.collapse": "Einklappen", "session.todo.expand": "Ausklappen", + "session.followupDock.summary.one": "{{count}} Nachricht in der Warteschlange", + "session.followupDock.summary.other": "{{count}} Nachrichten in der Warteschlange", + "session.followupDock.sendNow": "Jetzt senden", + "session.followupDock.edit": "Bearbeiten", + "session.followupDock.collapse": "Warteschlange einklappen", + "session.followupDock.expand": "Warteschlange ausklappen", + "session.revertDock.summary.one": "{{count}} zurückgesetzte Nachricht", + "session.revertDock.summary.other": "{{count}} zurückgesetzte Nachrichten", + "session.revertDock.collapse": "Zurückgesetzte Nachrichten einklappen", + "session.revertDock.expand": "Zurückgesetzte Nachrichten ausklappen", + "session.revertDock.restore": "Nachricht wiederherstellen", "session.new.title": "Baue, was du willst", "session.new.worktree.main": "Haupt-Branch", "session.new.worktree.mainWithBranch": "Haupt-Branch ({{branch}})", @@ -553,10 +575,21 @@ export const dict = { "settings.general.row.language.description": "Die Anzeigesprache für OpenCode ändern", "settings.general.row.appearance.title": "Erscheinungsbild", "settings.general.row.appearance.description": "Anpassen, wie OpenCode auf Ihrem Gerät aussieht", + "settings.general.row.colorScheme.title": "Farbschema", + "settings.general.row.colorScheme.description": + "Wählen Sie, ob OpenCode dem System-, hellen oder dunklen Thema folgt", "settings.general.row.theme.title": "Thema", "settings.general.row.theme.description": "Das Thema von OpenCode anpassen.", "settings.general.row.font.title": "Schriftart", "settings.general.row.font.description": "Die in Codeblöcken verwendete Monospace-Schriftart anpassen", + "settings.general.row.followup.title": "Verhalten bei Folgefragen", + "settings.general.row.followup.description": + "Wählen Sie, ob Folgefragen sofort steuern oder in einer Warteschlange warten", + "settings.general.row.followup.option.queue": "Warteschlange", + "settings.general.row.followup.option.steer": "Steuern", + "settings.general.row.reasoningSummaries.title": "Reasoning-Zusammenfassungen anzeigen", + "settings.general.row.reasoningSummaries.description": + "Zusammenfassungen des Modell-Reasonings in der Timeline anzeigen", "settings.general.row.shellToolPartsExpanded.title": "Shell-Tool-Abschnitte ausklappen", "settings.general.row.shellToolPartsExpanded.description": "Shell-Tool-Abschnitte standardmäßig in der Timeline ausgeklappt anzeigen", diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts index c87e7cb9d..b950cab8d 100644 --- a/packages/app/src/i18n/en.ts +++ b/packages/app/src/i18n/en.ts @@ -530,6 +530,12 @@ export const dict = { "session.todo.title": "Todos", "session.todo.collapse": "Collapse", "session.todo.expand": "Expand", + "session.followupDock.summary.one": "{{count}} queued message", + "session.followupDock.summary.other": "{{count}} queued messages", + "session.followupDock.sendNow": "Send now", + "session.followupDock.edit": "Edit", + "session.followupDock.collapse": "Collapse queued messages", + "session.followupDock.expand": "Expand queued messages", "session.revertDock.summary.one": "{{count}} rolled back message", "session.revertDock.summary.other": "{{count}} rolled back messages", "session.revertDock.collapse": "Collapse rolled back messages", @@ -638,10 +644,16 @@ export const dict = { "settings.general.row.language.description": "Change the display language for OpenCode", "settings.general.row.appearance.title": "Appearance", "settings.general.row.appearance.description": "Customise how OpenCode looks on your device", + "settings.general.row.colorScheme.title": "Color scheme", + "settings.general.row.colorScheme.description": "Choose whether OpenCode follows the system, light, or dark theme", "settings.general.row.theme.title": "Theme", "settings.general.row.theme.description": "Customise how OpenCode is themed.", "settings.general.row.font.title": "Font", "settings.general.row.font.description": "Customise the mono font used in code blocks", + "settings.general.row.followup.title": "Follow-up behavior", + "settings.general.row.followup.description": "Choose whether follow-up prompts steer immediately or wait in a queue", + "settings.general.row.followup.option.queue": "Queue", + "settings.general.row.followup.option.steer": "Steer", "settings.general.row.reasoningSummaries.title": "Show reasoning summaries", "settings.general.row.reasoningSummaries.description": "Display model reasoning summaries in the timeline", "settings.general.row.shellToolPartsExpanded.title": "Expand shell tool parts", diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts index 77ef7970c..a2633004c 100644 --- a/packages/app/src/i18n/es.ts +++ b/packages/app/src/i18n/es.ts @@ -113,6 +113,7 @@ export const dict = { "dialog.model.empty": "Sin resultados de modelos", "dialog.model.manage": "Gestionar modelos", "dialog.model.manage.description": "Personalizar qué modelos aparecen en el selector de modelos.", + "dialog.model.manage.provider.toggle": "Alternar todos los modelos de {{provider}}", "dialog.model.unpaid.freeModels.title": "Modelos gratuitos proporcionados por OpenCode", "dialog.model.unpaid.addMore.title": "Añadir más modelos de proveedores populares", @@ -314,6 +315,11 @@ export const dict = { "dialog.server.add.error": "No se pudo conectar al servidor", "dialog.server.add.checking": "Comprobando...", "dialog.server.add.button": "Añadir servidor", + "dialog.server.add.name": "Nombre del servidor (opcional)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Nombre de usuario (opcional)", + "dialog.server.add.password": "Contraseña (opcional)", + "dialog.server.edit.title": "Editar servidor", "dialog.server.default.title": "Servidor predeterminado", "dialog.server.default.description": "Conectar a este servidor al iniciar la app en lugar de iniciar un servidor local. Requiere reinicio.", @@ -393,6 +399,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Idioma", "toast.language.description": "Cambiado a {{language}}", @@ -499,10 +506,14 @@ export const dict = { "session.review.change.other": "Cambios", "session.review.loadingChanges": "Cargando cambios...", "session.review.empty": "No hay cambios en esta sesión aún", + "session.review.noVcs": "No se detectó Sistema de Control de Versiones Git, los cambios no se muestran", + "session.review.noSnapshot": + "El seguimiento de instantáneas está deshabilitado en la configuración, por lo que los cambios de sesión no están disponibles", "session.review.noChanges": "Sin cambios", "session.files.selectToOpen": "Selecciona un archivo para abrir", "session.files.all": "Todos los archivos", + "session.files.empty": "Sin archivos", "session.files.binaryContent": "Archivo binario (el contenido no puede ser mostrado)", "session.messages.renderEarlier": "Renderizar mensajes anteriores", @@ -515,6 +526,17 @@ export const dict = { "session.todo.title": "Tareas", "session.todo.collapse": "Contraer", "session.todo.expand": "Expandir", + "session.followupDock.summary.one": "{{count}} mensaje en cola", + "session.followupDock.summary.other": "{{count}} mensajes en cola", + "session.followupDock.sendNow": "Enviar ahora", + "session.followupDock.edit": "Editar", + "session.followupDock.collapse": "Contraer mensajes en cola", + "session.followupDock.expand": "Expandir mensajes en cola", + "session.revertDock.summary.one": "{{count}} mensaje revertido", + "session.revertDock.summary.other": "{{count}} mensajes revertidos", + "session.revertDock.collapse": "Contraer mensajes revertidos", + "session.revertDock.expand": "Expandir mensajes revertidos", + "session.revertDock.restore": "Restaurar mensaje", "session.new.title": "Construye lo que quieras", "session.new.worktree.main": "Rama principal", @@ -612,11 +634,20 @@ export const dict = { "settings.general.row.language.description": "Cambiar el idioma de visualización para OpenCode", "settings.general.row.appearance.title": "Apariencia", "settings.general.row.appearance.description": "Personaliza cómo se ve OpenCode en tu dispositivo", + "settings.general.row.colorScheme.title": "Esquema de color", + "settings.general.row.colorScheme.description": "Elige si OpenCode sigue el tema del sistema, claro u oscuro", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "Personaliza el tema de OpenCode.", "settings.general.row.font.title": "Fuente", "settings.general.row.font.description": "Personaliza la fuente monoespaciada usada en bloques de código", - + "settings.general.row.followup.title": "Comportamiento de seguimiento", + "settings.general.row.followup.description": + "Elige si los prompts de seguimiento se dirigen inmediatamente o esperan en una cola", + "settings.general.row.followup.option.queue": "Cola", + "settings.general.row.followup.option.steer": "Dirigir", + "settings.general.row.reasoningSummaries.title": "Mostrar resúmenes de razonamiento", + "settings.general.row.reasoningSummaries.description": + "Mostrar resúmenes del razonamiento del modelo en la línea de tiempo", "settings.general.row.shellToolPartsExpanded.title": "Expandir partes de la herramienta shell", "settings.general.row.shellToolPartsExpanded.description": "Mostrar las partes de la herramienta shell expandidas por defecto en la línea de tiempo", diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts index c887f9ee8..cbde19316 100644 --- a/packages/app/src/i18n/fr.ts +++ b/packages/app/src/i18n/fr.ts @@ -104,6 +104,7 @@ export const dict = { "dialog.model.empty": "Aucun résultat de modèle", "dialog.model.manage": "Gérer les modèles", "dialog.model.manage.description": "Personnalisez les modèles qui apparaissent dans le sélecteur.", + "dialog.model.manage.provider.toggle": "Basculer tous les modèles {{provider}}", "dialog.model.unpaid.freeModels.title": "Modèles gratuits fournis par OpenCode", "dialog.model.unpaid.addMore.title": "Ajouter plus de modèles de fournisseurs populaires", "dialog.provider.viewAll": "Voir plus de fournisseurs", @@ -288,6 +289,11 @@ export const dict = { "dialog.server.add.error": "Impossible de se connecter au serveur", "dialog.server.add.checking": "Vérification...", "dialog.server.add.button": "Ajouter un serveur", + "dialog.server.add.name": "Nom du serveur (optionnel)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Nom d'utilisateur (optionnel)", + "dialog.server.add.password": "Mot de passe (optionnel)", + "dialog.server.edit.title": "Modifier le serveur", "dialog.server.default.title": "Serveur par défaut", "dialog.server.default.description": "Se connecter à ce serveur au lancement de l'application au lieu de démarrer un serveur local. Nécessite un redémarrage.", @@ -360,6 +366,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Langue", "toast.language.description": "Passé à {{language}}", "toast.theme.title": "Thème changé", @@ -451,8 +458,12 @@ export const dict = { "session.review.loadingChanges": "Chargement des modifications...", "session.review.empty": "Aucune modification dans cette session pour l'instant", "session.review.noChanges": "Aucune modification", + "session.review.noVcs": "Aucun système de contrôle de version Git détecté, modifications non affichées", + "session.review.noSnapshot": + "Le suivi des instantanés est désactivé dans la configuration, les modifications de session sont donc indisponibles", "session.files.selectToOpen": "Sélectionnez un fichier à ouvrir", "session.files.all": "Tous les fichiers", + "session.files.empty": "Aucun fichier", "session.files.binaryContent": "Fichier binaire (le contenu ne peut pas être affiché)", "session.messages.renderEarlier": "Afficher les messages précédents", "session.messages.loadingEarlier": "Chargement des messages précédents...", @@ -463,6 +474,17 @@ export const dict = { "session.todo.title": "Tâches", "session.todo.collapse": "Réduire", "session.todo.expand": "Développer", + "session.followupDock.summary.one": "{{count}} message en file d'attente", + "session.followupDock.summary.other": "{{count}} messages en file d'attente", + "session.followupDock.sendNow": "Envoyer maintenant", + "session.followupDock.edit": "Modifier", + "session.followupDock.collapse": "Réduire les messages en file d'attente", + "session.followupDock.expand": "Développer les messages en file d'attente", + "session.revertDock.summary.one": "{{count}} message annulé", + "session.revertDock.summary.other": "{{count}} messages annulés", + "session.revertDock.collapse": "Réduire les messages annulés", + "session.revertDock.expand": "Développer les messages annulés", + "session.revertDock.restore": "Restaurer le message", "session.new.title": "Créez ce que vous voulez", "session.new.worktree.main": "Branche principale", "session.new.worktree.mainWithBranch": "Branche principale ({{branch}})", @@ -550,10 +572,20 @@ export const dict = { "settings.general.row.language.description": "Changer la langue d'affichage pour OpenCode", "settings.general.row.appearance.title": "Apparence", "settings.general.row.appearance.description": "Personnaliser l'apparence d'OpenCode sur votre appareil", + "settings.general.row.colorScheme.title": "Schéma de couleurs", + "settings.general.row.colorScheme.description": "Choisissez si OpenCode suit le thème système, clair ou sombre", "settings.general.row.theme.title": "Thème", "settings.general.row.theme.description": "Personnaliser le thème d'OpenCode.", "settings.general.row.font.title": "Police", "settings.general.row.font.description": "Personnaliser la police mono utilisée dans les blocs de code", + "settings.general.row.followup.title": "Comportement de suivi", + "settings.general.row.followup.description": + "Choisissez si les messages de suivi dirigent immédiatement ou attendent dans une file d'attente", + "settings.general.row.followup.option.queue": "File d'attente", + "settings.general.row.followup.option.steer": "Diriger", + "settings.general.row.reasoningSummaries.title": "Afficher les résumés de raisonnement", + "settings.general.row.reasoningSummaries.description": + "Afficher les résumés de raisonnement du modèle dans la chronologie", "settings.general.row.shellToolPartsExpanded.title": "Développer les parties de l'outil shell", "settings.general.row.shellToolPartsExpanded.description": "Afficher les parties de l'outil shell développées par défaut dans la chronologie", diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts index 9ddb6baf4..914ac5cd7 100644 --- a/packages/app/src/i18n/ja.ts +++ b/packages/app/src/i18n/ja.ts @@ -104,6 +104,7 @@ export const dict = { "dialog.model.empty": "モデルが見つかりません", "dialog.model.manage": "モデルを管理", "dialog.model.manage.description": "モデルセレクターに表示するモデルをカスタマイズします。", + "dialog.model.manage.provider.toggle": "すべての{{provider}}モデルを切り替え", "dialog.model.unpaid.freeModels.title": "OpenCodeが提供する無料モデル", "dialog.model.unpaid.addMore.title": "人気のプロバイダーからモデルを追加", "dialog.provider.viewAll": "さらにプロバイダーを表示", @@ -287,6 +288,11 @@ export const dict = { "dialog.server.add.error": "サーバーに接続できませんでした", "dialog.server.add.checking": "確認中...", "dialog.server.add.button": "サーバーを追加", + "dialog.server.add.name": "サーバー名 (オプション)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "ユーザー名 (オプション)", + "dialog.server.add.password": "パスワード (オプション)", + "dialog.server.edit.title": "サーバーを編集", "dialog.server.default.title": "デフォルトサーバー", "dialog.server.default.description": "ローカルサーバーを起動する代わりに、アプリ起動時にこのサーバーに接続します。再起動が必要です。", @@ -358,6 +364,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "言語", "toast.language.description": "{{language}}に切り替えました", "toast.theme.title": "テーマが切り替わりました", @@ -444,9 +451,12 @@ export const dict = { "session.review.change.other": "変更", "session.review.loadingChanges": "変更を読み込み中...", "session.review.empty": "このセッションでの変更はまだありません", + "session.review.noVcs": "Gitバージョン管理システムが検出されないため、変更は表示されません", + "session.review.noSnapshot": "設定でスナップショット追跡が無効になっているため、セッションの変更は利用できません", "session.review.noChanges": "変更なし", "session.files.selectToOpen": "開くファイルを選択", "session.files.all": "すべてのファイル", + "session.files.empty": "ファイルなし", "session.files.binaryContent": "バイナリファイル(内容を表示できません)", "session.messages.renderEarlier": "以前のメッセージを表示", "session.messages.loadingEarlier": "以前のメッセージを読み込み中...", @@ -457,6 +467,17 @@ export const dict = { "session.todo.title": "ToDo", "session.todo.collapse": "折りたたむ", "session.todo.expand": "展開", + "session.followupDock.summary.one": "{{count}} 件のメッセージが待機中", + "session.followupDock.summary.other": "{{count}} 件のメッセージが待機中", + "session.followupDock.sendNow": "今すぐ送信", + "session.followupDock.edit": "編集", + "session.followupDock.collapse": "待機中のメッセージを折りたたむ", + "session.followupDock.expand": "待機中のメッセージを展開", + "session.revertDock.summary.one": "{{count}} 件のロールバックされたメッセージ", + "session.revertDock.summary.other": "{{count}} 件のロールバックされたメッセージ", + "session.revertDock.collapse": "ロールバックされたメッセージを折りたたむ", + "session.revertDock.expand": "ロールバックされたメッセージを展開", + "session.revertDock.restore": "メッセージを復元", "session.new.title": "何でも作る", "session.new.worktree.main": "メインブランチ", "session.new.worktree.mainWithBranch": "メインブランチ ({{branch}})", @@ -542,10 +563,19 @@ export const dict = { "settings.general.row.language.description": "OpenCodeの表示言語を変更します", "settings.general.row.appearance.title": "外観", "settings.general.row.appearance.description": "デバイスでのOpenCodeの表示をカスタマイズします", + "settings.general.row.colorScheme.title": "配色", + "settings.general.row.colorScheme.description": "OpenCodeがシステム、ライト、またはダークテーマに従うかを選択します", "settings.general.row.theme.title": "テーマ", "settings.general.row.theme.description": "OpenCodeのテーマをカスタマイズします。", "settings.general.row.font.title": "フォント", "settings.general.row.font.description": "コードブロックで使用する等幅フォントをカスタマイズします", + "settings.general.row.followup.title": "フォローアップの動作", + "settings.general.row.followup.description": + "フォローアッププロンプトを即座に実行するか、キューで待機させるかを選択します", + "settings.general.row.followup.option.queue": "キューに追加", + "settings.general.row.followup.option.steer": "即座に実行 (Steer)", + "settings.general.row.reasoningSummaries.title": "推論の要約を表示", + "settings.general.row.reasoningSummaries.description": "タイムラインにモデルの推論の要約を表示します", "settings.general.row.shellToolPartsExpanded.title": "shell ツールパーツを展開", "settings.general.row.shellToolPartsExpanded.description": "タイムラインで shell ツールパーツをデフォルトで展開して表示します", diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts index 1e35106d1..f0a3f3ae6 100644 --- a/packages/app/src/i18n/ko.ts +++ b/packages/app/src/i18n/ko.ts @@ -108,6 +108,7 @@ export const dict = { "dialog.model.empty": "모델 결과 없음", "dialog.model.manage": "모델 관리", "dialog.model.manage.description": "모델 선택기에 표시할 모델 사용자 지정", + "dialog.model.manage.provider.toggle": "모든 {{provider}} 모델 토글", "dialog.model.unpaid.freeModels.title": "OpenCode에서 제공하는 무료 모델", "dialog.model.unpaid.addMore.title": "인기 공급자의 모델 추가", "dialog.provider.viewAll": "더 많은 공급자 보기", @@ -291,6 +292,11 @@ export const dict = { "dialog.server.add.error": "서버에 연결할 수 없습니다", "dialog.server.add.checking": "확인 중...", "dialog.server.add.button": "서버 추가", + "dialog.server.add.name": "서버 이름 (선택 사항)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "사용자 이름 (선택 사항)", + "dialog.server.add.password": "비밀번호 (선택 사항)", + "dialog.server.edit.title": "서버 편집", "dialog.server.default.title": "기본 서버", "dialog.server.default.description": "로컬 서버를 시작하는 대신 앱 실행 시 이 서버에 연결합니다. 다시 시작해야 합니다.", @@ -361,6 +367,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "언어", "toast.language.description": "{{language}}(으)로 전환됨", "toast.theme.title": "테마 전환됨", @@ -446,9 +453,12 @@ export const dict = { "session.review.change.other": "변경", "session.review.loadingChanges": "변경 사항 로드 중...", "session.review.empty": "이 세션에 변경 사항이 아직 없습니다", + "session.review.noVcs": "Git 버전 관리 시스템이 감지되지 않아 변경 사항이 표시되지 않습니다", + "session.review.noSnapshot": "구성에서 스냅샷 추적이 비활성화되어 있어 세션 변경 사항을 사용할 수 없습니다", "session.review.noChanges": "변경 없음", "session.files.selectToOpen": "열 파일을 선택하세요", "session.files.all": "모든 파일", + "session.files.empty": "파일 없음", "session.files.binaryContent": "바이너리 파일 (내용을 표시할 수 없음)", "session.messages.renderEarlier": "이전 메시지 렌더링", "session.messages.loadingEarlier": "이전 메시지 로드 중...", @@ -459,6 +469,17 @@ export const dict = { "session.todo.title": "할 일", "session.todo.collapse": "접기", "session.todo.expand": "펼치기", + "session.followupDock.summary.one": "{{count}}개의 대기 중인 메시지", + "session.followupDock.summary.other": "{{count}}개의 대기 중인 메시지", + "session.followupDock.sendNow": "지금 전송", + "session.followupDock.edit": "편집", + "session.followupDock.collapse": "대기 중인 메시지 접기", + "session.followupDock.expand": "대기 중인 메시지 펼치기", + "session.revertDock.summary.one": "{{count}}개의 롤백된 메시지", + "session.revertDock.summary.other": "{{count}}개의 롤백된 메시지", + "session.revertDock.collapse": "롤백된 메시지 접기", + "session.revertDock.expand": "롤백된 메시지 펼치기", + "session.revertDock.restore": "메시지 복원", "session.new.title": "무엇이든 만들기", "session.new.worktree.main": "메인 브랜치", "session.new.worktree.mainWithBranch": "메인 브랜치 ({{branch}})", @@ -543,10 +564,18 @@ export const dict = { "settings.general.row.language.description": "OpenCode 표시 언어 변경", "settings.general.row.appearance.title": "모양", "settings.general.row.appearance.description": "기기에서 OpenCode가 보이는 방식 사용자 지정", + "settings.general.row.colorScheme.title": "색상 테마", + "settings.general.row.colorScheme.description": "OpenCode가 시스템, 라이트 또는 다크 테마를 따를지 선택하세요", "settings.general.row.theme.title": "테마", "settings.general.row.theme.description": "OpenCode 테마 사용자 지정", "settings.general.row.font.title": "글꼴", "settings.general.row.font.description": "코드 블록에 사용되는 고정폭 글꼴 사용자 지정", + "settings.general.row.followup.title": "후속 조치 동작", + "settings.general.row.followup.description": "후속 프롬프트를 즉시 실행할지 대기열에 넣을지 선택하세요", + "settings.general.row.followup.option.queue": "대기열", + "settings.general.row.followup.option.steer": "조종", + "settings.general.row.reasoningSummaries.title": "추론 요약 표시", + "settings.general.row.reasoningSummaries.description": "타임라인에 모델 추론 요약 표시", "settings.general.row.shellToolPartsExpanded.title": "shell 도구 파트 펼치기", "settings.general.row.shellToolPartsExpanded.description": "타임라인에서 기본적으로 shell 도구 파트를 펼친 상태로 표시합니다", diff --git a/packages/app/src/i18n/no.ts b/packages/app/src/i18n/no.ts index d9dac8ee5..17ba96058 100644 --- a/packages/app/src/i18n/no.ts +++ b/packages/app/src/i18n/no.ts @@ -116,6 +116,7 @@ export const dict = { "dialog.model.empty": "Ingen modellresultater", "dialog.model.manage": "Administrer modeller", "dialog.model.manage.description": "Tilpass hvilke modeller som vises i modellvelgeren.", + "dialog.model.manage.provider.toggle": "Veksle alle {{provider}}-modeller", "dialog.model.unpaid.freeModels.title": "Gratis modeller levert av OpenCode", "dialog.model.unpaid.addMore.title": "Legg til flere modeller fra populære leverandører", @@ -216,7 +217,7 @@ export const dict = { "common.search.placeholder": "Søk", "common.goBack": "Gå tilbake", - "common.goForward": "Navigate forward", + "common.goForward": "Gå frem", "common.loading": "Laster", "common.loading.ellipsis": "...", "common.cancel": "Avbryt", @@ -317,6 +318,11 @@ export const dict = { "dialog.server.add.error": "Kunne ikke koble til server", "dialog.server.add.checking": "Sjekker...", "dialog.server.add.button": "Legg til server", + "dialog.server.add.name": "Servernavn (valgfritt)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Brukernavn (valgfritt)", + "dialog.server.add.password": "Passord (valgfritt)", + "dialog.server.edit.title": "Rediger server", "dialog.server.default.title": "Standardserver", "dialog.server.default.description": "Koble til denne serveren ved oppstart i stedet for å starte en lokal server. Krever omstart.", @@ -394,6 +400,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Språk", "toast.language.description": "Byttet til {{language}}", @@ -499,10 +506,14 @@ export const dict = { "session.review.change.other": "Endringer", "session.review.loadingChanges": "Laster endringer...", "session.review.empty": "Ingen endringer i denne sesjonen ennå", + "session.review.noVcs": "Ingen Git-versjonskontrollsystem oppdaget, endringer vises ikke", + "session.review.noSnapshot": + "Snapshot-sporing er deaktivert i konfigurasjonen, så sesjonsendringer er ikke tilgjengelige", "session.review.noChanges": "Ingen endringer", "session.files.selectToOpen": "Velg en fil å åpne", "session.files.all": "Alle filer", + "session.files.empty": "Ingen filer", "session.files.binaryContent": "Binær fil (innhold kan ikke vises)", "session.messages.renderEarlier": "Vis tidligere meldinger", @@ -515,6 +526,17 @@ export const dict = { "session.todo.title": "Oppgaver", "session.todo.collapse": "Skjul", "session.todo.expand": "Utvid", + "session.followupDock.summary.one": "{{count}} melding i kø", + "session.followupDock.summary.other": "{{count}} meldinger i kø", + "session.followupDock.sendNow": "Send nå", + "session.followupDock.edit": "Rediger", + "session.followupDock.collapse": "Skjul meldinger i kø", + "session.followupDock.expand": "Utvid meldinger i kø", + "session.revertDock.summary.one": "{{count}} tilbakestilt melding", + "session.revertDock.summary.other": "{{count}} tilbakestilte meldinger", + "session.revertDock.collapse": "Skjul tilbakestilte meldinger", + "session.revertDock.expand": "Utvid tilbakestilte meldinger", + "session.revertDock.restore": "Gjenopprett melding", "session.new.title": "Bygg hva som helst", "session.new.worktree.main": "Hovedgren", @@ -612,11 +634,18 @@ export const dict = { "settings.general.row.language.description": "Endre visningsspråket for OpenCode", "settings.general.row.appearance.title": "Utseende", "settings.general.row.appearance.description": "Tilpass hvordan OpenCode ser ut på enheten din", + "settings.general.row.colorScheme.title": "Fargevalg", + "settings.general.row.colorScheme.description": "Velg om OpenCode skal følge systemets, lyst eller mørkt tema", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "Tilpass hvordan OpenCode er tematisert.", "settings.general.row.font.title": "Skrift", "settings.general.row.font.description": "Tilpass mono-skriften som brukes i kodeblokker", - + "settings.general.row.followup.title": "Oppfølgingsadferd", + "settings.general.row.followup.description": "Velg om oppfølgingsspørsmål skal kjøres umiddelbart eller vente i kø", + "settings.general.row.followup.option.queue": "Kø", + "settings.general.row.followup.option.steer": "Styr", + "settings.general.row.reasoningSummaries.title": "Vis resonneringssammendrag", + "settings.general.row.reasoningSummaries.description": "Vis sammendrag av modellresonnering i tidslinjen", "settings.general.row.shellToolPartsExpanded.title": "Utvid shell-verktøydeler", "settings.general.row.shellToolPartsExpanded.description": "Vis shell-verktøydeler utvidet som standard i tidslinjen", "settings.general.row.editToolPartsExpanded.title": "Utvid edit-verktøydeler", diff --git a/packages/app/src/i18n/pl.ts b/packages/app/src/i18n/pl.ts index b63fe5ee4..38111c873 100644 --- a/packages/app/src/i18n/pl.ts +++ b/packages/app/src/i18n/pl.ts @@ -104,6 +104,7 @@ export const dict = { "dialog.model.empty": "Brak wyników modelu", "dialog.model.manage": "Zarządzaj modelami", "dialog.model.manage.description": "Dostosuj, które modele pojawiają się w wyborze modelu.", + "dialog.model.manage.provider.toggle": "Przełącz wszystkie modele {{provider}}", "dialog.model.unpaid.freeModels.title": "Darmowe modele dostarczane przez OpenCode", "dialog.model.unpaid.addMore.title": "Dodaj więcej modeli od popularnych dostawców", "dialog.provider.viewAll": "Zobacz więcej dostawców", @@ -289,6 +290,11 @@ export const dict = { "dialog.server.add.error": "Nie można połączyć się z serwerem", "dialog.server.add.checking": "Sprawdzanie...", "dialog.server.add.button": "Dodaj serwer", + "dialog.server.add.name": "Nazwa serwera (opcjonalnie)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Nazwa użytkownika (opcjonalnie)", + "dialog.server.add.password": "Hasło (opcjonalnie)", + "dialog.server.edit.title": "Edytuj serwer", "dialog.server.default.title": "Domyślny serwer", "dialog.server.default.description": "Połącz z tym serwerem przy uruchomieniu aplikacji zamiast uruchamiać lokalny serwer. Wymaga restartu.", @@ -359,6 +365,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Język", "toast.language.description": "Przełączono na {{language}}", "toast.theme.title": "Przełączono motyw", @@ -445,9 +452,12 @@ export const dict = { "session.review.change.other": "Zmiany", "session.review.loadingChanges": "Ładowanie zmian...", "session.review.empty": "Brak zmian w tej sesji", + "session.review.noVcs": "Nie wykryto systemu kontroli wersji Git, zmiany nie są wyświetlane", + "session.review.noSnapshot": "Śledzenie migawek jest wyłączone w konfiguracji, więc zmiany w sesji są niedostępne", "session.review.noChanges": "Brak zmian", "session.files.selectToOpen": "Wybierz plik do otwarcia", "session.files.all": "Wszystkie pliki", + "session.files.empty": "Brak plików", "session.files.binaryContent": "Plik binarny (zawartość nie może być wyświetlona)", "session.messages.renderEarlier": "Renderuj wcześniejsze wiadomości", "session.messages.loadingEarlier": "Ładowanie wcześniejszych wiadomości...", @@ -458,6 +468,17 @@ export const dict = { "session.todo.title": "Zadania", "session.todo.collapse": "Zwiń", "session.todo.expand": "Rozwiń", + "session.followupDock.summary.one": "{{count}} wiadomość w kolejce", + "session.followupDock.summary.other": "{{count}} wiadomości w kolejce", + "session.followupDock.sendNow": "Wyślij teraz", + "session.followupDock.edit": "Edytuj", + "session.followupDock.collapse": "Zwiń wiadomości w kolejce", + "session.followupDock.expand": "Rozwiń wiadomości w kolejce", + "session.revertDock.summary.one": "{{count}} cofnięta wiadomość", + "session.revertDock.summary.other": "{{count}} cofnięte wiadomości", + "session.revertDock.collapse": "Zwiń cofnięte wiadomości", + "session.revertDock.expand": "Rozwiń cofnięte wiadomości", + "session.revertDock.restore": "Przywróć wiadomość", "session.new.title": "Zbuduj cokolwiek", "session.new.worktree.main": "Główna gałąź", "session.new.worktree.mainWithBranch": "Główna gałąź ({{branch}})", @@ -543,10 +564,19 @@ export const dict = { "settings.general.row.language.description": "Zmień język wyświetlania dla OpenCode", "settings.general.row.appearance.title": "Wygląd", "settings.general.row.appearance.description": "Dostosuj wygląd OpenCode na swoim urządzeniu", + "settings.general.row.colorScheme.title": "Schemat kolorów", + "settings.general.row.colorScheme.description": + "Wybierz, czy OpenCode ma używać motywu systemowego, jasnego czy ciemnego", "settings.general.row.theme.title": "Motyw", "settings.general.row.theme.description": "Dostosuj motyw OpenCode.", "settings.general.row.font.title": "Czcionka", "settings.general.row.font.description": "Dostosuj czcionkę mono używaną w blokach kodu", + "settings.general.row.followup.title": "Zachowanie kontynuacji", + "settings.general.row.followup.description": "Wybierz, czy kontynuacja ma być natychmiastowa, czy czekać w kolejce", + "settings.general.row.followup.option.queue": "Kolejka", + "settings.general.row.followup.option.steer": "Sterowanie", + "settings.general.row.reasoningSummaries.title": "Pokaż podsumowania wnioskowania", + "settings.general.row.reasoningSummaries.description": "Wyświetlaj podsumowania wnioskowania modelu na osi czasu", "settings.general.row.shellToolPartsExpanded.title": "Rozwijaj elementy narzędzia shell", "settings.general.row.shellToolPartsExpanded.description": "Domyślnie pokazuj rozwinięte elementy narzędzia shell na osi czasu", diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts index aadb926d2..0b63e8422 100644 --- a/packages/app/src/i18n/ru.ts +++ b/packages/app/src/i18n/ru.ts @@ -113,6 +113,7 @@ export const dict = { "dialog.model.empty": "Модели не найдены", "dialog.model.manage": "Управление моделями", "dialog.model.manage.description": "Настройте какие модели появляются в выборе модели", + "dialog.model.manage.provider.toggle": "Переключить все модели {{provider}}", "dialog.model.unpaid.freeModels.title": "Бесплатные модели от OpenCode", "dialog.model.unpaid.addMore.title": "Добавьте больше моделей от популярных провайдеров", @@ -314,6 +315,11 @@ export const dict = { "dialog.server.add.error": "Не удалось подключиться к серверу", "dialog.server.add.checking": "Проверка...", "dialog.server.add.button": "Добавить сервер", + "dialog.server.add.name": "Имя сервера (необязательно)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Имя пользователя (необязательно)", + "dialog.server.add.password": "Пароль (необязательно)", + "dialog.server.edit.title": "Редактировать сервер", "dialog.server.default.title": "Сервер по умолчанию", "dialog.server.default.description": "Подключаться к этому серверу при запуске приложения вместо запуска локального сервера. Требуется перезапуск.", @@ -393,6 +399,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "Язык", "toast.language.description": "Переключено на {{language}}", @@ -499,9 +506,12 @@ export const dict = { "session.review.change.other": "Изменения", "session.review.loadingChanges": "Загрузка изменений...", "session.review.empty": "Изменений в этой сессии пока нет", + "session.review.noVcs": "Система контроля версий Git не обнаружена, изменения не отображаются", + "session.review.noSnapshot": "Отслеживание снимков отключено в настройках, поэтому изменения сессии недоступны", "session.review.noChanges": "Нет изменений", "session.files.selectToOpen": "Выберите файл, чтобы открыть", "session.files.all": "Все файлы", + "session.files.empty": "Нет файлов", "session.files.binaryContent": "Двоичный файл (содержимое не может быть отображено)", "session.messages.renderEarlier": "Показать предыдущие сообщения", "session.messages.loadingEarlier": "Загрузка предыдущих сообщений...", @@ -513,6 +523,17 @@ export const dict = { "session.todo.title": "Задачи", "session.todo.collapse": "Свернуть", "session.todo.expand": "Развернуть", + "session.followupDock.summary.one": "{{count}} сообщение в очереди", + "session.followupDock.summary.other": "{{count}} сообщений в очереди", + "session.followupDock.sendNow": "Отправить сейчас", + "session.followupDock.edit": "Редактировать", + "session.followupDock.collapse": "Свернуть сообщения в очереди", + "session.followupDock.expand": "Развернуть сообщения в очереди", + "session.revertDock.summary.one": "{{count}} сообщение возвращено", + "session.revertDock.summary.other": "{{count}} сообщений возвращено", + "session.revertDock.collapse": "Свернуть возвращённые сообщения", + "session.revertDock.expand": "Развернуть возвращённые сообщения", + "session.revertDock.restore": "Восстановить сообщение", "session.new.title": "Создавайте что угодно", "session.new.worktree.main": "Основная ветка", @@ -610,10 +631,19 @@ export const dict = { "settings.general.row.language.description": "Изменить язык отображения OpenCode", "settings.general.row.appearance.title": "Внешний вид", "settings.general.row.appearance.description": "Настройте как OpenCode выглядит на вашем устройстве", + "settings.general.row.colorScheme.title": "Цветовая схема", + "settings.general.row.colorScheme.description": "Выберите, следует ли OpenCode системной, светлой или тёмной теме", "settings.general.row.theme.title": "Тема", "settings.general.row.theme.description": "Настройте оформление OpenCode.", "settings.general.row.font.title": "Шрифт", "settings.general.row.font.description": "Настройте моноширинный шрифт для блоков кода", + "settings.general.row.followup.title": "Поведение уточняющих вопросов", + "settings.general.row.followup.description": + "Выберите, отправлять ли уточняющие вопросы сразу или помещать их в очередь", + "settings.general.row.followup.option.queue": "Очередь", + "settings.general.row.followup.option.steer": "Направлять", + "settings.general.row.reasoningSummaries.title": "Показывать сводки рассуждений", + "settings.general.row.reasoningSummaries.description": "Отображать сводки рассуждений модели в ленте", "settings.general.row.shellToolPartsExpanded.title": "Разворачивать элементы инструмента shell", "settings.general.row.shellToolPartsExpanded.description": @@ -767,30 +797,31 @@ export const dict = { "settings.permissions.tool.glob.description": "Сопоставление файлов по паттернам glob", "settings.permissions.tool.grep.title": "Grep", "settings.permissions.tool.grep.description": "Поиск по содержимому файлов с использованием регулярных выражений", - "settings.permissions.tool.list.title": "Список", + "settings.permissions.tool.list.title": "List", "settings.permissions.tool.list.description": "Список файлов в директории", "settings.permissions.tool.bash.title": "Bash", - "settings.permissions.tool.bash.description": "Выполнение команд оболочки", + "settings.permissions.tool.bash.description": "Запуск команд оболочки", "settings.permissions.tool.task.title": "Task", - "settings.permissions.tool.task.description": "Запуск под-агентов", + "settings.permissions.tool.task.description": "Запуск подагентов", "settings.permissions.tool.skill.title": "Skill", - "settings.permissions.tool.skill.description": "Загрузить навык по имени", + "settings.permissions.tool.skill.description": "Загрузка навыка по имени", "settings.permissions.tool.lsp.title": "LSP", - "settings.permissions.tool.lsp.description": "Выполнение запросов к языковому серверу", - "settings.permissions.tool.todoread.title": "Чтение списка задач", + "settings.permissions.tool.lsp.description": "Запросы к языковому серверу", + "settings.permissions.tool.todoread.title": "Todo Read", "settings.permissions.tool.todoread.description": "Чтение списка задач", - "settings.permissions.tool.todowrite.title": "Запись списка задач", + "settings.permissions.tool.todowrite.title": "Todo Write", "settings.permissions.tool.todowrite.description": "Обновление списка задач", "settings.permissions.tool.webfetch.title": "Web Fetch", - "settings.permissions.tool.webfetch.description": "Получить содержимое по URL", + "settings.permissions.tool.webfetch.description": "Получение контента по URL", "settings.permissions.tool.websearch.title": "Web Search", "settings.permissions.tool.websearch.description": "Поиск в интернете", - "settings.permissions.tool.codesearch.title": "Поиск кода", + "settings.permissions.tool.codesearch.title": "Code Search", "settings.permissions.tool.codesearch.description": "Поиск кода в интернете", "settings.permissions.tool.external_directory.title": "Внешняя директория", "settings.permissions.tool.external_directory.description": "Доступ к файлам вне директории проекта", "settings.permissions.tool.doom_loop.title": "Doom Loop", - "settings.permissions.tool.doom_loop.description": "Обнаружение повторных вызовов инструментов с одинаковым вводом", + "settings.permissions.tool.doom_loop.description": + "Обнаружение повторяющихся вызовов инструментов с одинаковыми входными данными", "session.delete.failed.title": "Не удалось удалить сессию", "session.delete.title": "Удалить сессию", @@ -807,21 +838,21 @@ export const dict = { "workspace.reset.failed.title": "Не удалось сбросить рабочее пространство", "workspace.reset.success.title": "Рабочее пространство сброшено", "workspace.reset.success.description": "Рабочее пространство теперь соответствует ветке по умолчанию.", - "workspace.error.stillPreparing": "Рабочее пространство всё ещё готовится", - "workspace.status.checking": "Проверка наличия неслитых изменений...", + "workspace.error.stillPreparing": "Рабочее пространство всё ещё подготавливается", + "workspace.status.checking": "Проверка незафиксированных изменений...", "workspace.status.error": "Не удалось проверить статус git.", - "workspace.status.clean": "Неслитые изменения не обнаружены.", - "workspace.status.dirty": "Обнаружены неслитые изменения в этом рабочем пространстве.", + "workspace.status.clean": "Незафиксированных изменений не обнаружено.", + "workspace.status.dirty": "В этом рабочем пространстве обнаружены незафиксированные изменения.", "workspace.delete.title": "Удалить рабочее пространство", "workspace.delete.confirm": 'Удалить рабочее пространство "{{name}}"?', "workspace.delete.button": "Удалить рабочее пространство", "workspace.reset.title": "Сбросить рабочее пространство", "workspace.reset.confirm": 'Сбросить рабочее пространство "{{name}}"?', "workspace.reset.button": "Сбросить рабочее пространство", - "workspace.reset.archived.none": "Никакие активные сессии не будут архивированы.", + "workspace.reset.archived.none": "Активные сессии не будут архивированы.", "workspace.reset.archived.one": "1 сессия будет архивирована.", "workspace.reset.archived.many": "{{count}} сессий будет архивировано.", - "workspace.reset.note": "Рабочее пространство будет сброшено в соответствие с веткой по умолчанию.", + "workspace.reset.note": "Это сбросит рабочее пространство до соответствия ветке по умолчанию.", "common.open": "Открыть", "dialog.releaseNotes.action.getStarted": "Начать", "dialog.releaseNotes.action.next": "Далее", diff --git a/packages/app/src/i18n/th.ts b/packages/app/src/i18n/th.ts index 6a25a356a..94bb2c2c3 100644 --- a/packages/app/src/i18n/th.ts +++ b/packages/app/src/i18n/th.ts @@ -113,6 +113,7 @@ export const dict = { "dialog.model.empty": "ไม่พบผลลัพธ์โมเดล", "dialog.model.manage": "จัดการโมเดล", "dialog.model.manage.description": "ปรับแต่งโมเดลที่จะปรากฏในตัวเลือกโมเดล", + "dialog.model.manage.provider.toggle": "สลับโมเดลทั้งหมดของ {{provider}}", "dialog.model.unpaid.freeModels.title": "โมเดลฟรีที่จัดหาให้โดย OpenCode", "dialog.model.unpaid.addMore.title": "เพิ่มโมเดลเพิ่มเติมจากผู้ให้บริการยอดนิยม", @@ -314,6 +315,11 @@ export const dict = { "dialog.server.add.error": "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์", "dialog.server.add.checking": "กำลังตรวจสอบ...", "dialog.server.add.button": "เพิ่มเซิร์ฟเวอร์", + "dialog.server.add.name": "ชื่อเซิร์ฟเวอร์ (ไม่บังคับ)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "ชื่อผู้ใช้ (ไม่บังคับ)", + "dialog.server.add.password": "รหัสผ่าน (ไม่บังคับ)", + "dialog.server.edit.title": "แก้ไขเซิร์ฟเวอร์", "dialog.server.default.title": "เซิร์ฟเวอร์เริ่มต้น", "dialog.server.default.description": "เชื่อมต่อกับเซิร์ฟเวอร์นี้เมื่อเปิดแอปแทนการเริ่มเซิร์ฟเวอร์ในเครื่อง ต้องรีสตาร์ท", @@ -391,6 +397,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "ภาษา", "toast.language.description": "สลับไปที่ {{language}}", @@ -494,9 +501,12 @@ export const dict = { "session.review.change.other": "การเปลี่ยนแปลง", "session.review.loadingChanges": "กำลังโหลดการเปลี่ยนแปลง...", "session.review.empty": "ยังไม่มีการเปลี่ยนแปลงในเซสชันนี้", + "session.review.noVcs": "ไม่ตรวจพบระบบควบคุมเวอร์ชัน Git การเปลี่ยนแปลงจะไม่แสดง", + "session.review.noSnapshot": "การติดตามสแนปชอตถูกปิดใช้งานในการกำหนดค่า ดังนั้นการเปลี่ยนแปลงเซสชันจึงไม่พร้อมใช้งาน", "session.review.noChanges": "ไม่มีการเปลี่ยนแปลง", "session.files.selectToOpen": "เลือกไฟล์เพื่อเปิด", + "session.files.empty": "ไม่มีไฟล์", "session.files.all": "ไฟล์ทั้งหมด", "session.files.binaryContent": "ไฟล์ไบนารี (ไม่สามารถแสดงเนื้อหาได้)", @@ -510,6 +520,17 @@ export const dict = { "session.todo.title": "สิ่งที่ต้องทำ", "session.todo.collapse": "ย่อ", "session.todo.expand": "ขยาย", + "session.followupDock.summary.one": "{{count}} ข้อความในคิว", + "session.followupDock.summary.other": "{{count}} ข้อความในคิว", + "session.followupDock.sendNow": "ส่งทันที", + "session.followupDock.edit": "แก้ไข", + "session.followupDock.collapse": "ย่อข้อความในคิว", + "session.followupDock.expand": "ขยายข้อความในคิว", + "session.revertDock.summary.one": "{{count}} ข้อความที่ถูกย้อนกลับ", + "session.revertDock.summary.other": "{{count}} ข้อความที่ถูกย้อนกลับ", + "session.revertDock.collapse": "ย่อข้อความที่ถูกย้อนกลับ", + "session.revertDock.expand": "ขยายข้อความที่ถูกย้อนกลับ", + "session.revertDock.restore": "กู้คืนข้อความ", "session.new.title": "สร้างอะไรก็ได้", "session.new.worktree.main": "สาขาหลัก", @@ -604,11 +625,18 @@ export const dict = { "settings.general.row.language.description": "เปลี่ยนภาษาที่แสดงสำหรับ OpenCode", "settings.general.row.appearance.title": "รูปลักษณ์", "settings.general.row.appearance.description": "ปรับแต่งวิธีการที่ OpenCode มีลักษณะบนอุปกรณ์ของคุณ", + "settings.general.row.colorScheme.title": "โทนสี", + "settings.general.row.colorScheme.description": "เลือกว่าจะให้ OpenCode ใช้ธีมตามระบบ สว่าง หรือมืด", "settings.general.row.theme.title": "ธีม", "settings.general.row.theme.description": "ปรับแต่งวิธีการที่ OpenCode มีธีม", "settings.general.row.font.title": "ฟอนต์", "settings.general.row.font.description": "ปรับแต่งฟอนต์โมโนที่ใช้ในบล็อกโค้ด", - + "settings.general.row.followup.title": "พฤติกรรมการติดตามผล", + "settings.general.row.followup.description": "เลือกว่าจะให้พร้อมท์ติดตามผลทำงานทันทีหรือรอในคิว", + "settings.general.row.followup.option.queue": "คิว", + "settings.general.row.followup.option.steer": "นำทาง", + "settings.general.row.reasoningSummaries.title": "แสดงสรุปการใช้เหตุผล", + "settings.general.row.reasoningSummaries.description": "แสดงสรุปการใช้เหตุผลของโมเดลในไทม์ไลน์", "settings.general.row.shellToolPartsExpanded.title": "ขยายส่วนเครื่องมือ shell", "settings.general.row.shellToolPartsExpanded.description": "แสดงส่วนเครื่องมือ shell แบบขยายตามค่าเริ่มต้นในไทม์ไลน์", "settings.general.row.editToolPartsExpanded.title": "ขยายส่วนเครื่องมือ edit", diff --git a/packages/app/src/i18n/tr.ts b/packages/app/src/i18n/tr.ts index 50e559832..66835c1c5 100644 --- a/packages/app/src/i18n/tr.ts +++ b/packages/app/src/i18n/tr.ts @@ -320,6 +320,11 @@ export const dict = { "dialog.server.add.error": "Sunucuya bağlanılamadı", "dialog.server.add.checking": "Kontrol ediliyor...", "dialog.server.add.button": "Sunucu ekle", + "dialog.server.add.name": "Sunucu adı (isteğe bağlı)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "Kullanıcı adı (isteğe bağlı)", + "dialog.server.add.password": "Şifre (isteğe bağlı)", + "dialog.server.edit.title": "Sunucuyu düzenle", "dialog.server.default.title": "Varsayılan sunucu", "dialog.server.default.description": "Uygulama başlatıldığında yerel sunucu başlatmak yerine bu sunucuya bağlan. Yeniden başlatma gerektirir.", @@ -506,10 +511,13 @@ export const dict = { "session.review.loadingChanges": "Değişiklikler yükleniyor...", "session.review.empty": "Bu oturumda henüz değişiklik yok", "session.review.noVcs": "Git VCS algılanamadı, oturum değişiklikleri tespit edilemeyecek", + "session.review.noSnapshot": + "Yapılandırmada anlık görüntü takibi devre dışı bırakıldı, bu nedenle oturum değişiklikleri kullanılamıyor", "session.review.noChanges": "Değişiklik yok", "session.files.selectToOpen": "Açmak için bir dosya seçin", "session.files.all": "Tüm dosyalar", + "session.files.empty": "Dosya yok", "session.files.binaryContent": "İkili dosya (içerik görüntülenemiyor)", "session.messages.renderEarlier": "Önceki mesajları göster", @@ -522,6 +530,17 @@ export const dict = { "session.todo.title": "Görevler", "session.todo.collapse": "Daralt", "session.todo.expand": "Genişlet", + "session.followupDock.summary.one": "{{count}} sıradaki mesaj", + "session.followupDock.summary.other": "{{count}} sıradaki mesaj", + "session.followupDock.sendNow": "Şimdi gönder", + "session.followupDock.edit": "Düzenle", + "session.followupDock.collapse": "Sıradaki mesajları daralt", + "session.followupDock.expand": "Sıradaki mesajları genişlet", + "session.revertDock.summary.one": "{{count}} geri alınan mesaj", + "session.revertDock.summary.other": "{{count}} geri alınan mesaj", + "session.revertDock.collapse": "Geri alınan mesajları daralt", + "session.revertDock.expand": "Geri alınan mesajları genişlet", + "session.revertDock.restore": "Mesajı geri yükle", "session.new.title": "İstediğini yap", "session.new.worktree.main": "Ana dal", @@ -618,10 +637,18 @@ export const dict = { "settings.general.row.language.description": "OpenCode'un görünüm dilini değiştirin", "settings.general.row.appearance.title": "Görünüm", "settings.general.row.appearance.description": "OpenCode'un cihazınızdaki görünümünü özelleştirin", + "settings.general.row.colorScheme.title": "Renk şeması", + "settings.general.row.colorScheme.description": + "OpenCode'un sistem, açık veya koyu temayı takip etip etmeyeceğini seçin", "settings.general.row.theme.title": "Tema", "settings.general.row.theme.description": "OpenCode'un temasını özelleştirin.", "settings.general.row.font.title": "Yazı Tipi", "settings.general.row.font.description": "Kod bloklarında kullanılan monospace yazı tipini özelleştirin", + "settings.general.row.followup.title": "Takip davranışı", + "settings.general.row.followup.description": + "Takip komutlarının hemen yönlendirilmesini mi yoksa sırada beklemesini mi istediğinizi seçin", + "settings.general.row.followup.option.queue": "Sıra", + "settings.general.row.followup.option.steer": "Yönlendir", "settings.general.row.reasoningSummaries.title": "Akıl yürütme özetlerini göster", "settings.general.row.reasoningSummaries.description": "Zaman çizelgesinde model akıl yürütme özetlerini görüntüle", "settings.general.row.shellToolPartsExpanded.title": "Kabuk araç bileşenlerini genişlet", diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts index 1f88a8222..d6b179c5c 100644 --- a/packages/app/src/i18n/zh.ts +++ b/packages/app/src/i18n/zh.ts @@ -140,6 +140,7 @@ export const dict = { "dialog.model.empty": "未找到模型", "dialog.model.manage": "管理模型", "dialog.model.manage.description": "自定义模型选择器中显示的模型。", + "dialog.model.manage.provider.toggle": "切换所有 {{provider}} 模型", "dialog.model.unpaid.freeModels.title": "OpenCode 提供的免费模型", "dialog.model.unpaid.addMore.title": "从热门提供商添加更多模型", @@ -334,6 +335,11 @@ export const dict = { "dialog.server.add.error": "无法连接到服务器", "dialog.server.add.checking": "检查中...", "dialog.server.add.button": "添加服务器", + "dialog.server.add.name": "服务器名称(可选)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "用户名(可选)", + "dialog.server.add.password": "密码(可选)", + "dialog.server.edit.title": "编辑服务器", "dialog.server.default.title": "默认服务器", "dialog.server.default.description": "应用启动时连接此服务器,而不是启动本地服务器。需要重启。", "dialog.server.default.none": "未选择服务器", @@ -406,6 +412,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "语言", "toast.language.description": "已切换到{{language}}", @@ -497,9 +504,12 @@ export const dict = { "session.review.change.other": "更改", "session.review.loadingChanges": "正在加载更改...", "session.review.empty": "此会话暂无更改", + "session.review.noVcs": "未检测到 Git 版本控制系统,无法显示更改", + "session.review.noSnapshot": "配置中已禁用快照跟踪,因此会话更改不可用", "session.review.noChanges": "无更改", "session.files.selectToOpen": "选择要打开的文件", "session.files.all": "所有文件", + "session.files.empty": "无文件", "session.files.binaryContent": "二进制文件(无法显示内容)", "session.messages.renderEarlier": "显示更早的消息", "session.messages.loadingEarlier": "正在加载更早的消息...", @@ -510,6 +520,17 @@ export const dict = { "session.todo.title": "待办事项", "session.todo.collapse": "折叠", "session.todo.expand": "展开", + "session.followupDock.summary.one": "{{count}} 条排队消息", + "session.followupDock.summary.other": "{{count}} 条排队消息", + "session.followupDock.sendNow": "立即发送", + "session.followupDock.edit": "编辑", + "session.followupDock.collapse": "折叠排队消息", + "session.followupDock.expand": "展开排队消息", + "session.revertDock.summary.one": "{{count}} 条已回滚消息", + "session.revertDock.summary.other": "{{count}} 条已回滚消息", + "session.revertDock.collapse": "折叠已回滚消息", + "session.revertDock.expand": "展开已回滚消息", + "session.revertDock.restore": "恢复消息", "session.new.title": "构建任何东西", "session.new.worktree.main": "主分支", "session.new.worktree.mainWithBranch": "主分支({{branch}})", @@ -604,10 +625,18 @@ export const dict = { "settings.general.row.language.description": "更改 OpenCode 的显示语言", "settings.general.row.appearance.title": "外观", "settings.general.row.appearance.description": "自定义 OpenCode 在你的设备上的外观", + "settings.general.row.colorScheme.title": "配色方案", + "settings.general.row.colorScheme.description": "选择 OpenCode 跟随系统、浅色或深色主题", "settings.general.row.theme.title": "主题", "settings.general.row.theme.description": "自定义 OpenCode 的主题。", "settings.general.row.font.title": "字体", "settings.general.row.font.description": "自定义代码块使用的等宽字体", + "settings.general.row.followup.title": "跟进消息行为", + "settings.general.row.followup.description": "选择跟进提示是立即引导还是在队列中等待", + "settings.general.row.followup.option.queue": "排队", + "settings.general.row.followup.option.steer": "引导", + "settings.general.row.reasoningSummaries.title": "显示推理摘要", + "settings.general.row.reasoningSummaries.description": "在时间线中显示模型推理摘要", "settings.general.row.shellToolPartsExpanded.title": "展开 shell 工具部分", "settings.general.row.shellToolPartsExpanded.description": "默认在时间线中展开 shell 工具部分", "settings.general.row.editToolPartsExpanded.title": "展开编辑工具部分", diff --git a/packages/app/src/i18n/zht.ts b/packages/app/src/i18n/zht.ts index a75e8ef47..3796350d2 100644 --- a/packages/app/src/i18n/zht.ts +++ b/packages/app/src/i18n/zht.ts @@ -117,6 +117,7 @@ export const dict = { "dialog.model.empty": "找不到模型", "dialog.model.manage": "管理模型", "dialog.model.manage.description": "自訂模型選擇器中顯示的模型。", + "dialog.model.manage.provider.toggle": "切換所有 {{provider}} 模型", "dialog.model.unpaid.freeModels.title": "OpenCode 提供的免費模型", "dialog.model.unpaid.addMore.title": "從熱門提供者新增更多模型", @@ -314,6 +315,11 @@ export const dict = { "dialog.server.add.error": "無法連線到伺服器", "dialog.server.add.checking": "檢查中...", "dialog.server.add.button": "新增伺服器", + "dialog.server.add.name": "伺服器名稱(選填)", + "dialog.server.add.namePlaceholder": "Localhost", + "dialog.server.add.username": "使用者名稱(選填)", + "dialog.server.add.password": "密碼(選填)", + "dialog.server.edit.title": "編輯伺服器", "dialog.server.default.title": "預設伺服器", "dialog.server.default.description": "應用程式啟動時連線此伺服器,而不是啟動本地伺服器。需要重新啟動。", "dialog.server.default.none": "未選擇伺服器", @@ -390,6 +396,7 @@ export const dict = { "language.br": "Português (Brasil)", "language.bs": "Bosanski", "language.th": "ไทย", + "language.tr": "Türkçe", "toast.language.title": "語言", "toast.language.description": "已切換到 {{language}}", @@ -493,8 +500,11 @@ export const dict = { "session.review.loadingChanges": "正在載入變更...", "session.review.empty": "此工作階段暫無變更", "session.review.noChanges": "沒有變更", + "session.review.noVcs": "未偵測到 Git 版本控制系統,無法顯示變更", + "session.review.noSnapshot": "設定中已停用快照追蹤,因此無法使用工作階段變更", "session.files.selectToOpen": "選取要開啟的檔案", "session.files.all": "所有檔案", + "session.files.empty": "沒有檔案", "session.files.binaryContent": "二進位檔案(無法顯示內容)", "session.messages.renderEarlier": "顯示更早的訊息", "session.messages.loadingEarlier": "正在載入更早的訊息...", @@ -506,6 +516,17 @@ export const dict = { "session.todo.title": "待辦事項", "session.todo.collapse": "折疊", "session.todo.expand": "展開", + "session.followupDock.summary.one": "{{count}} 則佇列訊息", + "session.followupDock.summary.other": "{{count}} 則佇列訊息", + "session.followupDock.sendNow": "立即傳送", + "session.followupDock.edit": "編輯", + "session.followupDock.collapse": "收合佇列訊息", + "session.followupDock.expand": "展開佇列訊息", + "session.revertDock.summary.one": "{{count}} 則已回復訊息", + "session.revertDock.summary.other": "{{count}} 則已回復訊息", + "session.revertDock.collapse": "收合已回復訊息", + "session.revertDock.expand": "展開已回復訊息", + "session.revertDock.restore": "還原訊息", "session.new.title": "建構任何東西", "session.new.worktree.main": "主分支", @@ -585,8 +606,8 @@ export const dict = { "settings.tab.general": "一般", "settings.tab.shortcuts": "快速鍵", "settings.desktop.section.wsl": "WSL", - "settings.desktop.wsl.title": "WSL integration", - "settings.desktop.wsl.description": "Run the OpenCode server inside WSL on Windows.", + "settings.desktop.wsl.title": "WSL 整合", + "settings.desktop.wsl.description": "在 Windows 上的 WSL 中執行 OpenCode 伺服器。", "settings.general.section.appearance": "外觀", "settings.general.section.notifications": "系統通知", @@ -599,10 +620,18 @@ export const dict = { "settings.general.row.language.description": "變更 OpenCode 的顯示語言", "settings.general.row.appearance.title": "外觀", "settings.general.row.appearance.description": "自訂 OpenCode 在你的裝置上的外觀", + "settings.general.row.colorScheme.title": "配色方案", + "settings.general.row.colorScheme.description": "選擇 OpenCode 要跟隨系統、淺色或深色主題", "settings.general.row.theme.title": "主題", "settings.general.row.theme.description": "自訂 OpenCode 的主題。", "settings.general.row.font.title": "字型", "settings.general.row.font.description": "自訂程式碼區塊使用的等寬字型", + "settings.general.row.followup.title": "後續追問行為", + "settings.general.row.followup.description": "選擇後續追問提示是立即引導還是進入佇列等待", + "settings.general.row.followup.option.queue": "佇列", + "settings.general.row.followup.option.steer": "引導", + "settings.general.row.reasoningSummaries.title": "顯示推理摘要", + "settings.general.row.reasoningSummaries.description": "在時間軸中顯示模型推理摘要", "settings.general.row.shellToolPartsExpanded.title": "展開 shell 工具區塊", "settings.general.row.shellToolPartsExpanded.description": "在時間軸中預設展開 shell 工具區塊", diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index b8d32fed4..7a8318374 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -35,8 +35,10 @@ import { useLanguage } from "@/context/language" import { useLayout } from "@/context/layout" import { usePrompt } from "@/context/prompt" import { useSDK } from "@/context/sdk" +import { useSettings } from "@/context/settings" import { useSync } from "@/context/sync" import { useTerminal } from "@/context/terminal" +import { type FollowupDraft, sendFollowupDraft } from "@/components/prompt-input/submit" import { createSessionComposerState, SessionComposerRegion } from "@/pages/session/composer" import { createOpenReviewFile, createSessionTabs, createSizing, focusTerminalById } from "@/pages/session/helpers" import { MessageTimeline } from "@/pages/session/message-timeline" @@ -47,11 +49,13 @@ import { SessionSidePanel } from "@/pages/session/session-side-panel" import { TerminalPanel } from "@/pages/session/terminal-panel" import { useSessionCommands } from "@/pages/session/use-session-commands" import { useSessionHashScroll } from "@/pages/session/use-session-hash-scroll" +import { Identifier } from "@/utils/id" import { extractPromptFromParts } from "@/utils/prompt" import { same } from "@/utils/same" import { formatServerError } from "@/utils/server-errors" const emptyUserMessages: UserMessage[] = [] +const emptyFollowups: (FollowupDraft & { id: string })[] = [] type SessionHistoryWindowInput = { sessionID: () => string | undefined @@ -270,6 +274,7 @@ export default function Page() { const language = useLanguage() const navigate = useNavigate() const sdk = useSDK() + const settings = useSettings() const prompt = usePrompt() const comments = useComments() const terminal = useTerminal() @@ -466,6 +471,17 @@ export default function Page() { deferRender: false, }) + const [followup, setFollowup] = createStore({ + items: {} as Record, + sending: {} as Record, + failed: {} as Record, + paused: {} as Record, + edit: {} as Record< + string, + { id: string; prompt: FollowupDraft["prompt"]; context: FollowupDraft["context"] } | undefined + >, + }) + createComputed((prev) => { const key = sessionKey() if (key !== prev) { @@ -1264,12 +1280,117 @@ export default function Page() { }) const busy = (sessionID: string) => { - if (sync.data.session_status[sessionID]?.type !== "idle") return true + if ((sync.data.session_status[sessionID] ?? { type: "idle" as const }).type !== "idle") return true return (sync.data.message[sessionID] ?? []).some( (item) => item.role === "assistant" && typeof item.time.completed !== "number", ) } + const queuedFollowups = createMemo(() => { + const id = params.id + if (!id) return emptyFollowups + return followup.items[id] ?? emptyFollowups + }) + + const editingFollowup = createMemo(() => { + const id = params.id + if (!id) return + return followup.edit[id] + }) + + const sendingFollowup = createMemo(() => { + const id = params.id + if (!id) return + return followup.sending[id] + }) + + const queueEnabled = createMemo(() => { + const id = params.id + if (!id) return false + return settings.general.followup() === "queue" && busy(id) && !composer.blocked() + }) + + const followupText = (item: FollowupDraft) => { + const text = item.prompt + .map((part) => { + if (part.type === "image") return `[image:${part.filename}]` + if (part.type === "file") return `[file:${part.path}]` + if (part.type === "agent") return `@${part.name}` + return part.content + }) + .join("") + .split(/\r?\n/) + .map((line) => line.trim()) + .find((line) => !!line) + + if (text) return text + return `[${language.t("common.attachment")}]` + } + + const queueFollowup = (draft: FollowupDraft) => { + setFollowup("items", draft.sessionID, (items) => [ + ...(items ?? []), + { id: Identifier.ascending("message"), ...draft }, + ]) + setFollowup("failed", draft.sessionID, undefined) + setFollowup("paused", draft.sessionID, undefined) + } + + const followupDock = createMemo(() => queuedFollowups().map((item) => ({ id: item.id, text: followupText(item) }))) + + const sendFollowup = (sessionID: string, id: string, opts?: { manual?: boolean }) => { + const item = (followup.items[sessionID] ?? []).find((entry) => entry.id === id) + if (!item) return Promise.resolve() + if (followup.sending[sessionID]) return Promise.resolve() + + if (opts?.manual) setFollowup("paused", sessionID, undefined) + setFollowup("sending", sessionID, id) + setFollowup("failed", sessionID, undefined) + + return sendFollowupDraft({ + client: sdk.client, + sync, + globalSync, + draft: item, + optimisticBusy: item.sessionDirectory === sdk.directory, + }) + .then((ok) => { + if (ok === false) return + setFollowup("items", sessionID, (items) => (items ?? []).filter((entry) => entry.id !== id)) + if (opts?.manual) resumeScroll() + }) + .catch((err) => { + setFollowup("failed", sessionID, id) + fail(err) + }) + .finally(() => { + setFollowup("sending", sessionID, (value) => (value === id ? undefined : value)) + }) + } + + const editFollowup = (id: string) => { + const sessionID = params.id + if (!sessionID) return + if (followup.sending[sessionID]) return + + const item = queuedFollowups().find((entry) => entry.id === id) + if (!item) return + + setFollowup("items", sessionID, (items) => (items ?? []).filter((entry) => entry.id !== id)) + setFollowup("failed", sessionID, (value) => (value === id ? undefined : value)) + setFollowup("edit", sessionID, { + id: item.id, + prompt: item.prompt, + context: item.context, + }) + } + + const clearFollowupEdit = () => { + const id = params.id + if (!id) return + setFollowup("edit", id, undefined) + } + const halt = (sessionID: string) => busy(sessionID) ? sdk.client.session.abort({ sessionID }).catch(() => {}) : Promise.resolve() @@ -1378,6 +1499,21 @@ export default function Page() { const actions = { fork, revert } + createEffect(() => { + const sessionID = params.id + if (!sessionID) return + + const item = queuedFollowups()[0] + if (!item) return + if (followup.sending[sessionID]) return + if (followup.failed[sessionID] === item.id) return + if (followup.paused[sessionID]) return + if (composer.blocked()) return + if (busy(sessionID)) return + + void sendFollowup(sessionID, item.id) + }) + createResizeObserver( () => promptDock, ({ height }) => { @@ -1537,6 +1673,27 @@ export default function Page() { resumeScroll() }} onResponseSubmit={resumeScroll} + followup={ + params.id + ? { + queue: queueEnabled, + items: followupDock(), + sending: sendingFollowup(), + edit: editingFollowup(), + onQueue: queueFollowup, + onAbort: () => { + const id = params.id + if (!id) return + setFollowup("paused", id, true) + }, + onSend: (id) => { + void sendFollowup(params.id!, id, { manual: true }) + }, + onEdit: editFollowup, + onEditLoaded: clearFollowupEdit, + } + : undefined + } revert={ rolled().length > 0 ? { diff --git a/packages/app/src/pages/session/composer/session-composer-region.tsx b/packages/app/src/pages/session/composer/session-composer-region.tsx index 0cca90180..2034fbead 100644 --- a/packages/app/src/pages/session/composer/session-composer-region.tsx +++ b/packages/app/src/pages/session/composer/session-composer-region.tsx @@ -8,9 +8,11 @@ import { getSessionHandoff, setSessionHandoff } from "@/pages/session/handoff" import { useSessionKey } from "@/pages/session/session-layout" import { SessionPermissionDock } from "@/pages/session/composer/session-permission-dock" import { SessionQuestionDock } from "@/pages/session/composer/session-question-dock" +import { SessionFollowupDock } from "@/pages/session/composer/session-followup-dock" import { SessionRevertDock } from "@/pages/session/composer/session-revert-dock" import type { SessionComposerState } from "@/pages/session/composer/session-composer-state" import { SessionTodoDock } from "@/pages/session/composer/session-todo-dock" +import type { FollowupDraft } from "@/components/prompt-input/submit" export function SessionComposerRegion(props: { state: SessionComposerState @@ -21,6 +23,17 @@ export function SessionComposerRegion(props: { onNewSessionWorktreeReset: () => void onSubmit: () => void onResponseSubmit: () => void + followup?: { + queue: () => boolean + items: { id: string; text: string }[] + sending?: string + edit?: { id: string; prompt: FollowupDraft["prompt"]; context: FollowupDraft["context"] } + onQueue: (draft: FollowupDraft) => void + onAbort: () => void + onSend: (id: string) => void + onEdit: (id: string) => void + onEditLoaded: () => void + } revert?: { items: { id: string; text: string }[] restoring?: string @@ -214,10 +227,23 @@ export function SessionComposerRegion(props: { "margin-top": `${-lift()}px`, }} > + + +
diff --git a/packages/app/src/pages/session/composer/session-followup-dock.tsx b/packages/app/src/pages/session/composer/session-followup-dock.tsx new file mode 100644 index 000000000..7d744f4e6 --- /dev/null +++ b/packages/app/src/pages/session/composer/session-followup-dock.tsx @@ -0,0 +1,109 @@ +import { For, Show, createMemo } from "solid-js" +import { createStore } from "solid-js/store" +import { Button } from "@opencode-ai/ui/button" +import { DockTray } from "@opencode-ai/ui/dock-surface" +import { IconButton } from "@opencode-ai/ui/icon-button" +import { useLanguage } from "@/context/language" + +export function SessionFollowupDock(props: { + items: { id: string; text: string }[] + sending?: string + onSend: (id: string) => void + onEdit: (id: string) => void +}) { + const language = useLanguage() + const [store, setStore] = createStore({ + collapsed: false, + }) + + const toggle = () => setStore("collapsed", (value) => !value) + const total = createMemo(() => props.items.length) + const label = createMemo(() => + language.t(total() === 1 ? "session.followupDock.summary.one" : "session.followupDock.summary.other", { + count: total(), + }), + ) + const preview = createMemo(() => props.items[0]?.text ?? "") + + return ( + +
{ + if (event.key !== "Enter" && event.key !== " ") return + event.preventDefault() + toggle() + }} + > + {label()} + + {preview()} + +
+ { + event.preventDefault() + event.stopPropagation() + }} + onClick={(event) => { + event.stopPropagation() + toggle() + }} + aria-label={ + store.collapsed ? language.t("session.followupDock.expand") : language.t("session.followupDock.collapse") + } + /> +
+
+ + +