diff --git a/packages/views/chat/components/chat-session-history.tsx b/packages/views/chat/components/chat-session-history.tsx index 6f75dc7e77..67a4febea8 100644 --- a/packages/views/chat/components/chat-session-history.tsx +++ b/packages/views/chat/components/chat-session-history.tsx @@ -124,22 +124,25 @@ export function ChatSessionHistory() { > - Delete chat session + {t(($) => $.session_history.delete_dialog.title)} {pendingDelete?.title - ? `"${pendingDelete.title}" and its messages will be permanently removed.` - : "This chat session and its messages will be permanently removed."} - {" "}This action cannot be undone. + ? t(($) => $.session_history.delete_dialog.description_with_title, { title: pendingDelete.title }) + : t(($) => $.session_history.delete_dialog.description_default)} - Cancel + + {t(($) => $.session_history.delete_dialog.cancel)} + - {deleteSession.isPending ? "Deleting..." : "Delete"} + {deleteSession.isPending + ? t(($) => $.session_history.delete_dialog.confirming) + : t(($) => $.session_history.delete_dialog.confirm)} @@ -228,13 +231,13 @@ function SessionItem({ e.stopPropagation(); onRequestDelete(); }} - aria-label="Delete chat session" + aria-label={t(($) => $.session_history.row_delete_aria)} /> } > - Delete + {t(($) => $.session_history.row_delete_tooltip)} ); diff --git a/packages/views/chat/components/chat-window.tsx b/packages/views/chat/components/chat-window.tsx index 3fbcfeacff..b793b78296 100644 --- a/packages/views/chat/components/chat-window.tsx +++ b/packages/views/chat/components/chat-window.tsx @@ -426,7 +426,7 @@ export function ChatWindow() { - {showHistory ? "Back to chat" : "Chat history"} + {showHistory ? t(($) => $.window.history_back_tooltip) : t(($) => $.window.history_show_tooltip)} diff --git a/packages/views/locales/en/chat.json b/packages/views/locales/en/chat.json index 1c976acaff..a02f37d3e2 100644 --- a/packages/views/locales/en/chat.json +++ b/packages/views/locales/en/chat.json @@ -31,6 +31,16 @@ "minutes": "{{count}}m ago", "hours": "{{count}}h ago", "days": "{{count}}d ago" + }, + "row_delete_aria": "Delete chat session", + "row_delete_tooltip": "Delete", + "delete_dialog": { + "title": "Delete chat session", + "description_with_title": "\"{{title}}\" and its messages will be permanently removed. This action cannot be undone.", + "description_default": "This chat session and its messages will be permanently removed. This action cannot be undone.", + "cancel": "Cancel", + "confirm": "Delete", + "confirming": "Deleting..." } }, "window": { @@ -46,7 +56,9 @@ "untitled": "New chat", "my_agents": "My agents", "others": "Others", - "no_agents": "No agents" + "no_agents": "No agents", + "history_show_tooltip": "Chat history", + "history_back_tooltip": "Back to chat" }, "empty_state": { "first_time_title": "Chat with your agents", diff --git a/packages/views/locales/en/projects.json b/packages/views/locales/en/projects.json index d00f747620..89b86a4922 100644 --- a/packages/views/locales/en/projects.json +++ b/packages/views/locales/en/projects.json @@ -61,6 +61,20 @@ "toast_project_deleted": "Project deleted", "toast_move_issue_failed": "Failed to move issue" }, + "resources": { + "section_header": "Resources", + "empty": "No resources attached.", + "add_button": "Add resource", + "popover_title": "Attach a GitHub repo", + "attached_badge": "attached", + "remove_tooltip": "Remove", + "url_placeholder": "https://github.com/owner/repo", + "url_submit": "Add", + "toast_attached": "Repository attached", + "toast_attach_failed": "Failed to attach", + "toast_removed": "Resource removed", + "toast_remove_failed": "Failed to remove resource" + }, "delete_dialog": { "title": "Delete project", "description": "This will delete the project. Issues will not be deleted but will be unlinked.", diff --git a/packages/views/locales/zh-Hans/chat.json b/packages/views/locales/zh-Hans/chat.json index 54b033f10a..0abcd571ec 100644 --- a/packages/views/locales/zh-Hans/chat.json +++ b/packages/views/locales/zh-Hans/chat.json @@ -29,6 +29,16 @@ "minutes": "{{count}} 分钟前", "hours": "{{count}} 小时前", "days": "{{count}} 天前" + }, + "row_delete_aria": "删除对话", + "row_delete_tooltip": "删除", + "delete_dialog": { + "title": "删除对话", + "description_with_title": "\"{{title}}\" 及其消息会被永久删除,无法撤销。", + "description_default": "此对话及其消息会被永久删除,无法撤销。", + "cancel": "取消", + "confirm": "删除", + "confirming": "删除中..." } }, "window": { @@ -44,7 +54,9 @@ "untitled": "新对话", "my_agents": "我的智能体", "others": "其他", - "no_agents": "暂无智能体" + "no_agents": "暂无智能体", + "history_show_tooltip": "对话历史", + "history_back_tooltip": "返回对话" }, "empty_state": { "first_time_title": "和你的智能体对话", diff --git a/packages/views/locales/zh-Hans/projects.json b/packages/views/locales/zh-Hans/projects.json index 807a56ebc7..4a15d4e88e 100644 --- a/packages/views/locales/zh-Hans/projects.json +++ b/packages/views/locales/zh-Hans/projects.json @@ -61,6 +61,20 @@ "toast_project_deleted": "已删除项目", "toast_move_issue_failed": "移动 issue 失败" }, + "resources": { + "section_header": "资源", + "empty": "还没有关联资源。", + "add_button": "添加资源", + "popover_title": "关联 GitHub 仓库", + "attached_badge": "已关联", + "remove_tooltip": "移除", + "url_placeholder": "https://github.com/owner/repo", + "url_submit": "添加", + "toast_attached": "已关联仓库", + "toast_attach_failed": "关联失败", + "toast_removed": "已移除资源", + "toast_remove_failed": "移除资源失败" + }, "delete_dialog": { "title": "删除项目", "description": "将删除这个项目。issue 不会被删除,只会从项目中解除关联。", diff --git a/packages/views/projects/components/project-resources-section.tsx b/packages/views/projects/components/project-resources-section.tsx index 58c100320b..6eb08a3ef0 100644 --- a/packages/views/projects/components/project-resources-section.tsx +++ b/packages/views/projects/components/project-resources-section.tsx @@ -26,6 +26,7 @@ import { TooltipTrigger, TooltipContent, } from "@multica/ui/components/ui/tooltip"; +import { useT } from "../../i18n"; // Project Resources sidebar section. // @@ -33,6 +34,7 @@ import { // so adding a new type means: (1) extend the API validator, (2) add a render // case here. No changes to the schema or query layer. export function ProjectResourcesSection({ projectId }: { projectId: string }) { + const { t } = useT("projects"); const wsId = useWorkspaceId(); const workspace = useCurrentWorkspace(); const [open, setOpen] = useState(true); @@ -56,9 +58,9 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) { resource_type: "github_repo", resource_ref: { url }, }); - toast.success("Repository attached"); + toast.success(t(($) => $.resources.toast_attached)); } catch (err) { - const msg = err instanceof Error ? err.message : "Failed to attach"; + const msg = err instanceof Error ? err.message : t(($) => $.resources.toast_attach_failed); toast.error(msg); } }; @@ -66,9 +68,9 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) { const handleRemove = async (resource: ProjectResource) => { try { await deleteResource.mutateAsync(resource.id); - toast.success("Resource removed"); + toast.success(t(($) => $.resources.toast_removed)); } catch { - toast.error("Failed to remove resource"); + toast.error(t(($) => $.resources.toast_remove_failed)); } }; @@ -78,7 +80,7 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) { className={`flex w-full items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors mb-2 hover:bg-accent/70 ${open ? "" : "text-muted-foreground hover:text-foreground"}`} onClick={() => setOpen(!open)} > - Resources + {t(($) => $.resources.section_header)} @@ -87,7 +89,7 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) {
{resources.length === 0 && (

- No resources attached. + {t(($) => $.resources.empty)}

)} {resources.map((resource) => ( @@ -106,13 +108,13 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) { className="h-7 px-2 text-xs text-muted-foreground hover:text-foreground" > - Add resource + {t(($) => $.resources.add_button)} } />
- Attach a GitHub repo + {t(($) => $.resources.popover_title)}
{workspace?.repos && workspace.repos.length > 0 && (
@@ -145,7 +147,7 @@ export function ProjectResourcesSection({ projectId }: { projectId: string }) { {isAttached && ( - attached + {t(($) => $.resources.attached_badge)} )} @@ -174,6 +176,7 @@ function ResourceRow({ resource: ProjectResource; onRemove: () => void; }) { + const { t } = useT("projects"); if (resource.resource_type === "github_repo") { const ref = resource.resource_ref as GithubRepoResourceRef; return ( @@ -198,7 +201,7 @@ function ResourceRow({ type="button" onClick={onRemove} className="opacity-0 group-hover:opacity-100 transition-opacity rounded-sm p-0.5 hover:bg-accent" - title="Remove" + title={t(($) => $.resources.remove_tooltip)} > @@ -214,7 +217,7 @@ function ResourceRow({ type="button" onClick={onRemove} className="rounded-sm p-0.5 hover:bg-accent" - title="Remove" + title={t(($) => $.resources.remove_tooltip)} > @@ -227,6 +230,7 @@ function CustomRepoForm({ }: { onSubmit: (url: string) => Promise | void; }) { + const { t } = useT("projects"); const [url, setUrl] = useState(""); const [submitting, setSubmitting] = useState(false); const handle = async (e: React.FormEvent) => { @@ -247,7 +251,7 @@ function CustomRepoForm({ type="url" value={url} onChange={(e) => setUrl(e.target.value)} - placeholder="https://github.com/owner/repo" + placeholder={t(($) => $.resources.url_placeholder)} className="flex-1 bg-transparent text-xs px-2 py-1 outline-none placeholder:text-muted-foreground" /> );