wip(app): i18n

This commit is contained in:
Adam
2026-01-20 15:00:46 -06:00
parent ef36af0e55
commit b13c269162
8 changed files with 167 additions and 64 deletions

View File

@@ -9,6 +9,7 @@ import {
} from "@opencode-ai/sdk/v2/client"
import { useData } from "../context"
import { useDiffComponent } from "../context/diff"
import { type UiI18nKey, type UiI18nParams, useI18n } from "../context/i18n"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { Binary } from "@opencode-ai/util/binary"
@@ -29,29 +30,31 @@ import { DateTime, DurationUnit, Interval } from "luxon"
import { createAutoScroll } from "../hooks"
import { createResizeObserver } from "@solid-primitives/resize-observer"
function computeStatusFromPart(part: PartType | undefined): string | undefined {
type Translator = (key: UiI18nKey, params?: UiI18nParams) => string
function computeStatusFromPart(part: PartType | undefined, t: Translator): string | undefined {
if (!part) return undefined
if (part.type === "tool") {
switch (part.tool) {
case "task":
return "Delegating work"
return t("ui.sessionTurn.status.delegating")
case "todowrite":
case "todoread":
return "Planning next steps"
return t("ui.sessionTurn.status.planning")
case "read":
return "Gathering context"
return t("ui.sessionTurn.status.gatheringContext")
case "list":
case "grep":
case "glob":
return "Searching the codebase"
return t("ui.sessionTurn.status.searchingCodebase")
case "webfetch":
return "Searching the web"
return t("ui.sessionTurn.status.searchingWeb")
case "edit":
case "write":
return "Making edits"
return t("ui.sessionTurn.status.makingEdits")
case "bash":
return "Running commands"
return t("ui.sessionTurn.status.runningCommands")
default:
return undefined
}
@@ -59,11 +62,11 @@ function computeStatusFromPart(part: PartType | undefined): string | undefined {
if (part.type === "reasoning") {
const text = part.text ?? ""
const match = text.trimStart().match(/^\*\*(.+?)\*\*/)
if (match) return `Thinking · ${match[1].trim()}`
return "Thinking"
if (match) return t("ui.sessionTurn.status.thinkingWithTopic", { topic: match[1].trim() })
return t("ui.sessionTurn.status.thinking")
}
if (part.type === "text") {
return "Gathering thoughts"
return t("ui.sessionTurn.status.gatheringThoughts")
}
return undefined
}
@@ -133,6 +136,7 @@ export function SessionTurn(
}
}>,
) {
const i18n = useI18n()
const data = useData()
const diffComponent = useDiffComponent()
@@ -328,12 +332,12 @@ export function SessionTurn(
const msgParts = data.store.part[msg.id] ?? emptyParts
for (let pi = msgParts.length - 1; pi >= 0; pi--) {
const part = msgParts[pi]
if (part) return computeStatusFromPart(part)
if (part) return computeStatusFromPart(part, i18n.t)
}
}
}
return computeStatusFromPart(last)
return computeStatusFromPart(last, i18n.t)
})
const status = createMemo(() => data.store.session_status[props.sessionID] ?? idle)
@@ -368,7 +372,7 @@ export function SessionTurn(
const interval = Interval.fromDateTimes(from, to)
const unit: DurationUnit[] = interval.length("seconds") > 60 ? ["minutes", "seconds"] : ["seconds"]
return interval.toDuration(unit).normalize().toHuman({
return interval.toDuration(unit).normalize().reconfigure({ locale: i18n.locale() }).toHuman({
notation: "compact",
unitDisplay: "narrow",
compactDisplay: "short",
@@ -532,13 +536,18 @@ export function SessionTurn(
})()}
</span>
<span data-slot="session-turn-retry-seconds">
· retrying {store.retrySeconds > 0 ? `in ${store.retrySeconds}s ` : ""}
· {i18n.t("ui.sessionTurn.retry.retrying")}
{store.retrySeconds > 0
? " " + i18n.t("ui.sessionTurn.retry.inSeconds", { seconds: store.retrySeconds })
: ""}
</span>
<span data-slot="session-turn-retry-attempt">(#{retry()?.attempt})</span>
</Match>
<Match when={working()}>{store.status ?? "Considering next steps"}</Match>
<Match when={props.stepsExpanded}>Hide steps</Match>
<Match when={!props.stepsExpanded}>Show steps</Match>
<Match when={working()}>
{store.status ?? i18n.t("ui.sessionTurn.status.consideringNextSteps")}
</Match>
<Match when={props.stepsExpanded}>{i18n.t("ui.sessionTurn.steps.hide")}</Match>
<Match when={!props.stepsExpanded}>{i18n.t("ui.sessionTurn.steps.show")}</Match>
</Switch>
<span>·</span>
<span>{store.duration}</span>
@@ -580,7 +589,7 @@ export function SessionTurn(
<Show when={!working() && (response() || hasDiffs())}>
<div data-slot="session-turn-summary-section">
<div data-slot="session-turn-summary-header">
<h2 data-slot="session-turn-summary-title">Response</h2>
<h2 data-slot="session-turn-summary-title">{i18n.t("ui.sessionTurn.summary.response")}</h2>
<Markdown
data-slot="session-turn-markdown"
data-diffs={hasDiffs()}
@@ -657,8 +666,9 @@ export function SessionTurn(
})
}}
>
Show more changes (
{(data.store.session_diff?.[props.sessionID]?.length ?? 0) - store.diffLimit})
{i18n.t("ui.sessionTurn.diff.showMore", {
count: (data.store.session_diff?.[props.sessionID]?.length ?? 0) - store.diffLimit,
})}
</Button>
</Show>
</div>