Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useDialog } from "../ui/dialog"
import { createStore } from "solid-js/store"
import { For } from "solid-js"
import { useKeyboard } from "@opentui/solid"
import { useLanguage } from "@tui/context/language"

export function DialogSessionDeleteFailed(props: {
session: string
Expand All @@ -14,21 +15,22 @@ export function DialogSessionDeleteFailed(props: {
}) {
const dialog = useDialog()
const { theme } = useTheme()
const { t } = useLanguage()
const [store, setStore] = createStore({
active: "delete" as "delete" | "restore",
})

const options = [
{
id: "delete" as const,
title: "Delete workspace",
description: "Delete the workspace and all sessions attached to it.",
title: t("tui.delete_failed.title_delete"),
description: t("tui.delete_failed.desc_delete"),
run: props.onDelete,
},
{
id: "restore" as const,
title: "Restore to new workspace",
description: "Try to restore this session into a new workspace.",
title: t("tui.delete_failed.title_restore"),
description: t("tui.delete_failed.desc_restore"),
run: props.onRestore,
},
]
Expand Down Expand Up @@ -56,17 +58,17 @@ export function DialogSessionDeleteFailed(props: {
<box paddingLeft={2} paddingRight={2} gap={1}>
<box flexDirection="row" justifyContent="space-between">
<text attributes={TextAttributes.BOLD} fg={theme.text}>
Failed to Delete Session
{t("tui.delete_failed.title")}
</text>
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
esc
</text>
</box>
<text fg={theme.textMuted} wrapMode="word">
{`The session "${props.session}" could not be deleted because the workspace "${props.workspace}" is not available.`}
{t("tui.delete_failed.session_unavailable", { session: props.session, workspace: props.workspace })}
</text>
<text fg={theme.textMuted} wrapMode="word">
Choose how you want to recover this broken workspace session.
{t("tui.delete_failed.choose_recovery")}
</text>
<box flexDirection="column" paddingBottom={1} gap={1}>
<For each={options}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { createStore } from "solid-js/store"
import { For } from "solid-js"
import { useTheme } from "../context/theme"
import { useDialog } from "../ui/dialog"
import { useLanguage } from "@tui/context/language"

export function DialogWorkspaceUnavailable(props: { onRestore?: () => boolean | void | Promise<boolean | void> }) {
const dialog = useDialog()
const { theme } = useTheme()
const { t } = useLanguage()
const [store, setStore] = createStore({
active: "restore" as "cancel" | "restore",
})
Expand Down Expand Up @@ -40,24 +42,25 @@ export function DialogWorkspaceUnavailable(props: { onRestore?: () => boolean |
evt.preventDefault()
evt.stopPropagation()
setStore("active", "restore")
return
}
})

return (
<box paddingLeft={2} paddingRight={2} gap={1}>
<box flexDirection="row" justifyContent="space-between">
<text attributes={TextAttributes.BOLD} fg={theme.text}>
Workspace Unavailable
{t("tui.workspace_unavailable.title")}
</text>
<text fg={theme.textMuted} onMouseUp={() => dialog.clear()}>
esc
</text>
</box>
<text fg={theme.textMuted} wrapMode="word">
This session is attached to a workspace that is no longer available.
{t("tui.workspace_unavailable.description")}
</text>
<text fg={theme.textMuted} wrapMode="word">
Would you like to restore this session into a new workspace?
{t("tui.workspace_unavailable.restore_prompt")}
</text>
<box flexDirection="row" justifyContent="flex-end" paddingBottom={1} gap={1}>
<For each={options}>
Expand All @@ -71,7 +74,9 @@ export function DialogWorkspaceUnavailable(props: { onRestore?: () => boolean |
void confirm()
}}
>
<text fg={item === store.active ? theme.selectedListItemText : theme.textMuted}>{item}</text>
<text fg={item === store.active ? theme.selectedListItemText : theme.textMuted}>
{t(`tui.workspace_unavailable.${item}` as any)}
</text>
</box>
)}
</For>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { useTheme } from "../context/theme"
import { useLanguage } from "@tui/context/language"

export function PluginRouteMissing(props: { id: string; onHome: () => void }) {
const { theme } = useTheme()
const { t } = useLanguage()

return (
<box width="100%" height="100%" alignItems="center" justifyContent="center" flexDirection="column" gap={1}>
<text fg={theme.warning}>Unknown plugin route: {props.id}</text>
<text fg={theme.warning}>{t("tui.plugin_route_missing.unknown", { id: props.id })}</text>
<box onMouseUp={props.onHome} backgroundColor={theme.backgroundElement} paddingLeft={1} paddingRight={1}>
<text fg={theme.text}>go home</text>
<text fg={theme.text}>{t("tui.plugin_route_missing.go_home")}</text>
</box>
</box>
)
Expand Down
21 changes: 20 additions & 1 deletion packages/opencode/src/cli/cmd/tui/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,4 +428,23 @@ export const dict: Record<string, string> = {
"trust.dangerous.advice_root": "Unless you have a very specific reason, DO NOT trust the filesystem root.",
"trust.dangerous.option.yes": "I understand the risks, trust for this session",
"trust.dangerous.option.no": "Exit (recommended)",
}
// Session delete failed dialog
"tui.delete_failed.title": "Failed to Delete Session",
"tui.delete_failed.session_unavailable": "The session \"{{session}}\" could not be deleted because the workspace \"{{workspace}}\" is not available.",
"tui.delete_failed.choose_recovery": "Choose how you want to recover this broken workspace session.",
"tui.delete_failed.title_delete": "Delete workspace",
"tui.delete_failed.desc_delete": "Delete the workspace and all sessions attached to it.",
"tui.delete_failed.title_restore": "Restore to new workspace",
"tui.delete_failed.desc_restore": "Try to restore this session into a new workspace.",

// Workspace unavailable dialog
"tui.workspace_unavailable.title": "Workspace Unavailable",
"tui.workspace_unavailable.description": "This session is attached to a workspace that is no longer available.",
"tui.workspace_unavailable.restore_prompt": "Would you like to restore this session into a new workspace?",
"tui.workspace_unavailable.cancel": "cancel",
"tui.workspace_unavailable.restore": "restore",

// Plugin route missing
"tui.plugin_route_missing.unknown": "Unknown plugin route: {{id}}",
"tui.plugin_route_missing.go_home": "go home"
}
19 changes: 19 additions & 0 deletions packages/opencode/src/cli/cmd/tui/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,23 @@ export const dict = {
"trust.dangerous.advice_root": "除非有明确的理由,否则不要信任文件系统根目录。",
"trust.dangerous.option.yes": "我了解风险,仅本次信任",
"trust.dangerous.option.no": "退出(推荐)",
// Session delete failed dialog
"tui.delete_failed.title": "删除会话失败",
"tui.delete_failed.session_unavailable": "会话 \"{{session}}\" 无法删除,因为工作区 \"{{workspace}}\" 不可用。",
"tui.delete_failed.choose_recovery": "选择如何恢复此损坏的工作区会话。",
"tui.delete_failed.title_delete": "删除工作区",
"tui.delete_failed.desc_delete": "删除工作区及其关联的所有会话。",
"tui.delete_failed.title_restore": "恢复到新工作区",
"tui.delete_failed.desc_restore": "尝试将此会话恢复到新的工作区。",

// Workspace unavailable dialog
"tui.workspace_unavailable.title": "工作区不可用",
"tui.workspace_unavailable.description": "此会话关联的工作区已不可用。",
"tui.workspace_unavailable.restore_prompt": "是否将此会话恢复到新的工作区?",
"tui.workspace_unavailable.cancel": "取消",
"tui.workspace_unavailable.restore": "恢复",

// Plugin route missing
"tui.plugin_route_missing.unknown": "未知插件路由:{{id}}",
"tui.plugin_route_missing.go_home": "返回首页"
} satisfies Partial<Record<Keys, string>>