Files
fusion/packages/dashboard/app/components/MergeDetails.tsx
gsxdsm 1e49494bac feat(i18n): full-sweep string migration — 5,930 keys across 5 locales (#1352)
Migration (multi-agent sweep over 216 files, 60 batches):
- Every user-visible dashboard + TUI string moved to t() with the exact
  English inline default (en rendering byte-identical)
- Catalogs merged from per-batch fragments: en/zh-CN/zh-TW/fr/es now
  carry ~5,930 keys each across common/app/errors/cli namespaces;
  CLI bundles regenerated (6 locales incl. ko)

Integration fixes:
- 18 type errors: reserved {{count}} interpolations renamed, malformed
  plural call, hand-rolled t-param types replaced with TFunction<"app">
- 23 lint errors: superseded label constants/helpers removed
- ExecutorStatusBar hook-order violation (keyboard-open early return
  moved below hooks)
- TUI tests wrapped in I18nextProvider (uninitialized fallback renders
  literal {{placeholders}}); dashboard vitest.setup boots a minimal en
  i18next instance for the same reason

Known WIP (next commits): ~457 residual strings across 50 batches,
Korean drafts for swept keys, and a dashboard test-suite pass that is
still being stabilized (~283 failures under investigation — fake-timer
waitFor interaction, likely stale node_modules vs merged lockfile).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 19:06:53 -07:00

98 lines
3.8 KiB
TypeScript

import { useTranslation } from "react-i18next";
import type { Task } from "@fusion/core";
interface MergeDetailsProps {
task: Task;
}
function shortSha(sha?: string, t?: (key: string, defaultValue: string) => string): string {
if (!sha) return t ? t("merge.unknown", "Unknown") : "Unknown";
return sha.slice(0, 7);
}
export function MergeDetails({ task }: MergeDetailsProps) {
const { t } = useTranslation("app");
if (task.column !== "done" || !task.mergeDetails) {
return null;
}
const details = task.mergeDetails;
return (
<div className="detail-section">
<h4>{t("merge.title", "Merge Details")}</h4>
<div className="pr-card merge-details-card">
<div className="detail-log-entry">
<div className="detail-log-header">
<span className="detail-log-action">{t("merge.status", "Status")}</span>
<span className="detail-log-outcome">{details.mergeConfirmed === false ? t("merge.recordedNoConfirm", "Recorded without local merge confirmation") : t("merge.mergedSuccess", "Merged successfully")}</span>
</div>
</div>
<div className="detail-log-entry">
<div className="detail-log-header">
<span className="detail-log-action">{t("merge.commit", "Commit")}</span>
<span className="detail-log-outcome">{shortSha(details.commitSha, t)}</span>
</div>
</div>
<div className="detail-log-entry">
<div className="detail-log-header">
<span
className="detail-log-action"
title={t("merge.shortstatTitle", "Final commit shortstat; for the full landed diff across all task commits, see the Changes tab.")}
>
{t("merge.filesChanged", "Files in merge commit")}
</span>
<span className="detail-log-outcome">{details.filesChanged ?? 0}</span>
</div>
</div>
<div className="detail-log-entry">
<div className="detail-log-header">
<span
className="detail-log-action"
title={t("merge.shortstatTitle", "Final commit shortstat; for the full landed diff across all task commits, see the Changes tab.")}
>
{t("merge.insertionsDeletions", "Merge-commit insertions / deletions")}
</span>
<span className="detail-log-outcome">+{details.insertions ?? 0} / -{details.deletions ?? 0}</span>
</div>
</div>
{details.mergedAt ? (
<div className="detail-log-entry">
<div className="detail-log-header">
<span className="detail-log-action">{t("merge.mergedAt", "Merged at")}</span>
<span className="detail-log-outcome">{new Date(details.mergedAt).toLocaleString()}</span>
</div>
</div>
) : null}
{details.prNumber ? (
<div className="detail-log-entry">
<div className="detail-log-header">
<span className="detail-log-action">{t("merge.pr", "PR")}</span>
{task.prInfo?.url ? (
<a
className="detail-source-link detail-log-outcome"
href={task.prInfo.url}
target="_blank"
rel="noopener noreferrer"
>
#{details.prNumber}
</a>
) : (
<span className="detail-log-outcome">#{details.prNumber}</span>
)}
</div>
</div>
) : null}
{details.mergeCommitMessage ? (
<div className="detail-log-entry">
<div className="detail-log-header">
<span className="detail-log-action">{t("merge.message", "Message")}</span>
</div>
<div className="detail-log-outcome">{details.mergeCommitMessage}</div>
</div>
) : null}
</div>
</div>
);
}