i18n: a run's cards, its failure and the workspace's notes in the reader's language

run.tsx, desk.tsx, project.tsx and landing.tsx hand their t to turn.ts
(cards, failure, said, scrub) and to plain and unhonoured, so the notes
built with a value (Started on {branch}) translate. The log level is
still read from the English line.
This commit is contained in:
2026-10-22 19:09:05 -07:00
parent 9be9aaecc1
commit fb5424ad5b
4 changed files with 10 additions and 10 deletions
+1 -1
View File
@@ -99,7 +99,7 @@ export function Desk({
const { t: say } = useI18n()
const name = repo.split('/').filter(Boolean).pop() || repo
const lines = shell(events)
const failed = failure(events)
const failed = failure(events, say)
const box = useBox(sandbox)
// Nothing is said of the sandbox until it has been read.
const held = box.value?.state ?? ''
+4 -4
View File
@@ -238,7 +238,7 @@ export function Landing({ onStarted }: { onStarted: (session: string) => void })
return
}
// A plan or a setup routed to a machine is refused here, in its own words, before it leaves the page.
const why = unhonoured(mode, place.id)
const why = unhonoured(mode, place.id, t)
if (why) {
setNote(why)
return
@@ -281,7 +281,7 @@ export function Landing({ onStarted }: { onStarted: (session: string) => void })
setIssue(0)
onStarted(run.session)
} catch (e) {
setNote(plain(e, repo?.name ?? hub?.full_name ?? 'a new project', 'run'))
setNote(plain(e, repo?.name ?? hub?.full_name ?? t('a new project'), 'run', t))
} finally {
setBusy(false)
}
@@ -497,9 +497,9 @@ export function Landing({ onStarted }: { onStarted: (session: string) => void })
)}
</XStack>
) : null}
{note || unhonoured(mode, place.id) || mind.note ? (
{note || unhonoured(mode, place.id, t) || mind.note ? (
<SizableText size="$1" color="$soft" role="status">
{note || unhonoured(mode, place.id) || mind.note}
{note || unhonoured(mode, place.id, t) || mind.note}
</SizableText>
) : null}
<Prompt
+3 -3
View File
@@ -393,11 +393,11 @@ export function Project({ at }: { at: Where }) {
.map((e): Line => {
// The console is where a run's error is read whole; the chat says it in one plain line.
const body = decode(e.payload)
const error = e.kind === 'status' && body && typeof body === 'object' && typeof body.error === 'string' ? scrub(body.error) : ''
const error = e.kind === 'status' && body && typeof body === 'object' && typeof body.error === 'string' ? scrub(body.error, t) : ''
return {
id: `r${e.seq || e.id}`,
level: error || (e.kind === 'status' && /error/.test(said(e, run.record?.mode).toLowerCase())) ? 'error' : e.kind === 'tool-call' ? 'info' : 'log',
text: error || said(e, run.record?.mode),
text: error || said(e, run.record?.mode, t),
source: e.kind === 'status' ? 'run' : who(e.actor),
}
})
@@ -566,7 +566,7 @@ export function Project({ at }: { at: Where }) {
<Turn run={r} open={r.id === current} onOpen={() => setChosen(r.id)} project={slug} />
{r.id === current ? (
<YStack gap="$1" paddingInlineStart="$2" borderInlineStartWidth={1} borderColor="$borderColor">
{fold(run.events.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e, run.record?.mode) })).filter((b) => b.text)).map((b) => (
{fold(run.events.map((e) => ({ kind: e.kind, actor: who(e.actor), seq: e.seq, id: e.id, text: said(e, run.record?.mode, t) })).filter((b) => b.text)).map((b) => (
<SizableText key={b.key} size="$1" color="$soft">
{b.text}
</SizableText>
+2 -2
View File
@@ -102,11 +102,11 @@ export function Run({ id }: { id: string }) {
const mode = record?.mode ?? ''
// A run that narrated no ask of its own opens with the one its title records, once it has said anything.
const shown = useMemo(() => {
const drawn = cards(events, mode)
const drawn = cards(events, mode, say)
const ask = record ? headline(record.title, record.repo) : ''
const opens = drawn[0]?.kind === 'said' && drawn[0].who === 'person'
return ask && drawn.length && !opens ? [{ kind: 'said' as const, key: 'ask', who: 'person' as const, text: ask }, ...drawn] : drawn
}, [events, mode, record])
}, [events, mode, record, say])
const end = outcome(events)
const plan = useMemo(() => steps(events), [events])
const kept = useMemo(() => settled(events), [events])