diff --git a/integration/element-module/src/product-experience/BilingualSearchPanel.tsx b/integration/element-module/src/product-experience/BilingualSearchPanel.tsx index 0eca7d20..41f5a284 100644 --- a/integration/element-module/src/product-experience/BilingualSearchPanel.tsx +++ b/integration/element-module/src/product-experience/BilingualSearchPanel.tsx @@ -43,6 +43,16 @@ function normalizedStatus(job: TranslationJobProjection | null): string { return String(job?.status || "").trim().toLowerCase(); } +function translationStatusLabel(status: string): string { + if (!status) return "已更新"; + if (status === "queued") return "排队中"; + if (status === "running") return "进行中"; + if (status === "success") return "已完成"; + if (status === "failed") return "失败"; + if (status === "cancelled") return "已取消"; + return "状态未知"; +} + function formatTime(value: string): string { const parsed = Date.parse(value); if (!Number.isFinite(parsed)) return ""; @@ -78,7 +88,7 @@ export function BilingualSearchPanel({ const [query, setQuery] = useState(""); const [results, setResults] = useState({ query: "", contacts: [], messages: [] }); const [searchState, setSearchState] = useState<"idle" | "loading" | "ready" | "error">("idle"); - const [status, setStatus] = useState("Search messages in original text or Chinese translation."); + const [status, setStatus] = useState("搜索原文、姓名或中文翻译。"); const [activeMessageId, setActiveMessageId] = useState(""); const [activeJob, setActiveJob] = useState(null); const [jobTransportError, setJobTransportError] = useState(""); @@ -110,23 +120,23 @@ export function BilingualSearchPanel({ if (!trimmed) { setSearchState("idle"); setResults({ query: "", contacts: [], messages: [] }); - setStatus("Search messages in original text or Chinese translation."); + setStatus("搜索原文、姓名或中文翻译。"); return; } setSearchState("loading"); - setStatus(`Searching for “${trimmed}”…`); + setStatus(`正在搜索“${trimmed}”…`); try { const next = await searchWorkspace(trimmed); if (sequence !== searchSequence.current) return; setResults(next); setSearchState("ready"); const count = next.messages.length + next.contacts.length; - setStatus(count ? `${count} search results ready.` : `No results for “${trimmed}”.`); + setStatus(count ? `找到 ${count} 条结果。` : `没有找到“${trimmed}”的结果。`); } catch (error) { if (sequence !== searchSequence.current) return; setSearchState("error"); - setStatus(errorText(error, "Search is temporarily unavailable.")); + setStatus(errorText(error, "搜索暂不可用。")); } }; @@ -137,7 +147,7 @@ export function BilingualSearchPanel({ searchSequence.current += 1; setSearchState("idle"); setResults({ query: "", contacts: [], messages: [] }); - setStatus("Search messages in original text or Chinese translation."); + setStatus("搜索原文、姓名或中文翻译。"); return undefined; } @@ -166,7 +176,7 @@ export function BilingualSearchPanel({ setActiveJob(next); setJobTransportError(""); const nextStatus = normalizedStatus(next); - setStatus(`Translation ${nextStatus || "updated"}: ${Math.round(next.progress)}%.`); + setStatus(`翻译${translationStatusLabel(nextStatus)}:${Math.round(next.progress)}%。`); if (ACTIVE_JOB_STATES.has(nextStatus)) { schedulePoll(); } else if (nextStatus === "success" && latestQuery.current.trim()) { @@ -175,9 +185,9 @@ export function BilingualSearchPanel({ } catch (error) { if (disposed) return; failures += 1; - setJobTransportError(errorText(error, "Translation status is temporarily unavailable.")); + setJobTransportError(errorText(error, "翻译状态暂不可用。")); if (failures >= MAX_POLL_FAILURES) { - setStatus("Translation status polling paused after repeated connection failures."); + setStatus("连续连接失败,已暂停轮询翻译状态。你可以稍后重试。 "); return; } schedulePoll(Math.min(JOB_POLL_MS * (2 ** failures), MAX_POLL_BACKOFF_MS)); @@ -200,17 +210,17 @@ export function BilingualSearchPanel({ setActiveMessageId(messageId); setActiveJob(null); setJobTransportError(""); - setStatus("Creating translation task…"); + setStatus("正在创建翻译任务…"); try { const job = await createTranslationJob(messageId); if (sequence !== translationSequence.current) return; setActiveJob(job); - setStatus(`Translation ${normalizedStatus(job) || "queued"}: ${Math.round(job.progress)}%.`); + setStatus(`翻译${translationStatusLabel(normalizedStatus(job) || "queued")}:${Math.round(job.progress)}%。`); } catch (error) { if (sequence !== translationSequence.current) return; setActiveJob(null); - setJobTransportError(errorText(error, "Unable to create translation task.")); - setStatus(errorText(error, "Unable to create translation task.")); + setJobTransportError(errorText(error, "无法创建翻译任务。")); + setStatus(errorText(error, "无法创建翻译任务。")); } }; @@ -220,9 +230,9 @@ export function BilingualSearchPanel({ const job = await cancelTranslationJob(activeJob.id); setActiveJob(job); setJobTransportError(""); - setStatus("Translation cancelled."); + setStatus("翻译已取消。"); } catch (error) { - setJobTransportError(errorText(error, "Unable to cancel translation task.")); + setJobTransportError(errorText(error, "无法取消翻译任务。")); } }; @@ -233,16 +243,16 @@ export function BilingualSearchPanel({ setActiveJob(job); setActiveMessageId(job.messageId || activeMessageId); setJobTransportError(""); - setStatus(`Translation ${normalizedStatus(job) || "queued"}: ${Math.round(job.progress)}%.`); + setStatus(`翻译${translationStatusLabel(normalizedStatus(job) || "queued")}:${Math.round(job.progress)}%。`); } catch (error) { - setJobTransportError(errorText(error, "Unable to retry translation task.")); + setJobTransportError(errorText(error, "无法重试翻译任务。")); } }; const navigateResult = async (result: BilingualSearchResult): Promise => { const relationship = relationshipForResult(result, relationships); if (!relationship) { - setStatus("This result has no available relationship context yet."); + setStatus("这条结果暂时没有可用的关系上下文。"); return; } @@ -254,18 +264,18 @@ export function BilingualSearchPanel({ try { const navigated = await onNavigateRelationship(relationship); if (navigated) { - setStatus("Opened the authoritative Element conversation."); + setStatus("已打开可信的 Element 会话。"); return; } } catch (error) { - navigationError = errorText(error, "Element navigation is unavailable."); + navigationError = errorText(error, "Element 导航暂不可用。"); } } onSelectRelationship(relationship.id); setStatus(navigationError - ? `Opened relationship context. Element navigation failed: ${navigationError}` - : "Opened relationship context. Exact Element message navigation is unavailable for this result."); + ? `已打开关系上下文。Element 导航失败:${navigationError}` + : "已打开关系上下文;这条结果暂时无法精确跳转到 Element 消息。 "); }; const clearSearch = (): void => { @@ -273,7 +283,7 @@ export function BilingualSearchPanel({ setQuery(""); setResults({ query: "", contacts: [], messages: [] }); setSearchState("idle"); - setStatus("Search cleared."); + setStatus("搜索已清除。"); }; return ( @@ -281,7 +291,7 @@ export function BilingualSearchPanel({ className="yance-bilingual-search" data-expanded={expanded || undefined} data-reduced-motion={reducedMotion || undefined} - aria-label="Bilingual message search" + aria-label="双语消息搜索" >
{expanded && query ? ( - + ) : null}
{expanded ? (