fix(frontend): localize conversation export failures (#4493)

This commit is contained in:
Ryker_Feng 2026-07-27 22:52:36 +08:00 committed by GitHub
parent a9a5fc9ced
commit 3549dbf871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 33 additions and 26 deletions

View File

@ -12,10 +12,7 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"; } from "@/components/ui/dropdown-menu";
import { useI18n } from "@/core/i18n/hooks"; import { useI18n } from "@/core/i18n/hooks";
import { import { exportThread, type ThreadExportFormat } from "@/core/threads/export";
exportThreadAsJSON,
exportThreadAsMarkdown,
} from "@/core/threads/export";
import type { AgentThread } from "@/core/threads/types"; import type { AgentThread } from "@/core/threads/types";
import { useThread } from "./messages/context"; import { useThread } from "./messages/context";
@ -28,23 +25,23 @@ export function ExportTrigger({ threadId }: { threadId: string }) {
const messages = thread.messages; const messages = thread.messages;
const handleExport = useCallback( const handleExport = useCallback(
(format: "markdown" | "json") => { (format: ThreadExportFormat) => {
if (messages.length === 0) { if (messages.length === 0) {
toast.error(t.conversation.noMessages); toast.error(t.conversation.noMessages);
return; return;
} }
const agentThread = { try {
thread_id: threadId, const agentThread = {
updated_at: new Date().toISOString(), thread_id: threadId,
values: thread.values, updated_at: new Date().toISOString(),
} as AgentThread; values: thread.values,
} as AgentThread;
if (format === "markdown") { exportThread(agentThread, messages, format);
exportThreadAsMarkdown(agentThread, messages); toast.success(t.common.exportSuccess);
} else { } catch {
exportThreadAsJSON(agentThread, messages); toast.error(t.common.exportFailed);
} }
toast.success(t.common.exportSuccess);
}, },
[messages, thread.values, threadId, t], [messages, thread.values, threadId, t],
); );

View File

@ -48,10 +48,7 @@ import { resetThreadChatAfterDelete } from "@/components/workspace/chats/use-thr
import { getAPIClient } from "@/core/api"; import { getAPIClient } from "@/core/api";
import { writeTextToClipboard } from "@/core/clipboard"; import { writeTextToClipboard } from "@/core/clipboard";
import { useI18n } from "@/core/i18n/hooks"; import { useI18n } from "@/core/i18n/hooks";
import { import { exportThread, type ThreadExportFormat } from "@/core/threads/export";
exportThreadAsJSON,
exportThreadAsMarkdown,
} from "@/core/threads/export";
import { import {
useDeleteThread, useDeleteThread,
useInfiniteThreads, useInfiniteThreads,
@ -239,7 +236,7 @@ export function RecentChatList() {
); );
const handleExport = useCallback( const handleExport = useCallback(
async (thread: AgentThread, format: "markdown" | "json") => { async (thread: AgentThread, format: ThreadExportFormat) => {
try { try {
const apiClient = getAPIClient(); const apiClient = getAPIClient();
const state = await apiClient.threads.getState<AgentThreadState>( const state = await apiClient.threads.getState<AgentThreadState>(
@ -250,14 +247,10 @@ export function RecentChatList() {
toast.error(t.conversation.noMessages); toast.error(t.conversation.noMessages);
return; return;
} }
if (format === "markdown") { exportThread(thread, messages, format);
exportThreadAsMarkdown(thread, messages);
} else {
exportThreadAsJSON(thread, messages);
}
toast.success(t.common.exportSuccess); toast.success(t.common.exportSuccess);
} catch { } catch {
toast.error("Failed to export conversation"); toast.error(t.common.exportFailed);
} }
}, },
[t], [t],

View File

@ -51,6 +51,7 @@ export const enUS: Translations = {
exportAsMarkdown: "Export as Markdown", exportAsMarkdown: "Export as Markdown",
exportAsJSON: "Export as JSON", exportAsJSON: "Export as JSON",
exportSuccess: "Conversation exported", exportSuccess: "Conversation exported",
exportFailed: "Failed to export conversation.",
regenerate: "Regenerate", regenerate: "Regenerate",
editAndRerun: "Edit and rerun", editAndRerun: "Edit and rerun",
updateAndRerun: "Update and rerun", updateAndRerun: "Update and rerun",

View File

@ -40,6 +40,7 @@ export interface Translations {
exportAsMarkdown: string; exportAsMarkdown: string;
exportAsJSON: string; exportAsJSON: string;
exportSuccess: string; exportSuccess: string;
exportFailed: string;
regenerate: string; regenerate: string;
editAndRerun: string; editAndRerun: string;
updateAndRerun: string; updateAndRerun: string;

View File

@ -51,6 +51,7 @@ export const zhCN: Translations = {
exportAsMarkdown: "导出为 Markdown", exportAsMarkdown: "导出为 Markdown",
exportAsJSON: "导出为 JSON", exportAsJSON: "导出为 JSON",
exportSuccess: "对话已导出", exportSuccess: "对话已导出",
exportFailed: "导出对话失败。",
regenerate: "重新生成", regenerate: "重新生成",
editAndRerun: "编辑并重新运行", editAndRerun: "编辑并重新运行",
updateAndRerun: "更新并重新运行", updateAndRerun: "更新并重新运行",

View File

@ -30,6 +30,8 @@ export interface ExportOptions {
includeHidden?: boolean; includeHidden?: boolean;
} }
export type ThreadExportFormat = "markdown" | "json";
function visibleMessages( function visibleMessages(
messages: Message[], messages: Message[],
options: ExportOptions, options: ExportOptions,
@ -222,3 +224,15 @@ export function exportThreadAsJSON(thread: AgentThread, messages: Message[]) {
const filename = `${sanitizeFilename(titleOfThread(thread))}.json`; const filename = `${sanitizeFilename(titleOfThread(thread))}.json`;
downloadAsFile(json, filename, "application/json;charset=utf-8"); downloadAsFile(json, filename, "application/json;charset=utf-8");
} }
export function exportThread(
thread: AgentThread,
messages: Message[],
format: ThreadExportFormat,
) {
if (format === "markdown") {
exportThreadAsMarkdown(thread, messages);
} else {
exportThreadAsJSON(thread, messages);
}
}