chore(app): i18n sync (#15362)

This commit is contained in:
Adam
2026-02-27 09:45:00 -06:00
committed by GitHub
parent e5ae6c51b0
commit 6ef3af73df
65 changed files with 1096 additions and 71 deletions

View File

@@ -463,14 +463,22 @@ function contextToolTrigger(part: ToolPart, i18n: ReturnType<typeof useI18n>) {
}
}
function contextToolSummary(parts: ToolPart[]) {
function contextToolSummary(parts: ToolPart[], i18n: ReturnType<typeof useI18n>) {
const read = parts.filter((part) => part.tool === "read").length
const search = parts.filter((part) => part.tool === "glob" || part.tool === "grep").length
const list = parts.filter((part) => part.tool === "list").length
return [
read ? `${read} ${read === 1 ? "read" : "reads"}` : undefined,
search ? `${search} ${search === 1 ? "search" : "searches"}` : undefined,
list ? `${list} ${list === 1 ? "list" : "lists"}` : undefined,
read
? i18n.t(read === 1 ? "ui.messagePart.context.read.one" : "ui.messagePart.context.read.other", { count: read })
: undefined,
search
? i18n.t(search === 1 ? "ui.messagePart.context.search.one" : "ui.messagePart.context.search.other", {
count: search,
})
: undefined,
list
? i18n.t(list === 1 ? "ui.messagePart.context.list.one" : "ui.messagePart.context.list.other", { count: list })
: undefined,
].filter((value): value is string => !!value)
}
@@ -595,7 +603,7 @@ function ContextToolGroup(props: { parts: ToolPart[]; busy?: boolean }) {
() =>
!!props.busy || props.parts.some((part) => part.state.status === "pending" || part.state.status === "running"),
)
const summary = createMemo(() => contextToolSummary(props.parts))
const summary = createMemo(() => contextToolSummary(props.parts, i18n))
const details = createMemo(() => summary().join(", "))
return (
@@ -979,7 +987,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
return (
<div style="width: 100%; display: flex; justify-content: flex-end;">
<span class="text-13-regular text-text-weak cursor-default">
{i18n.t("ui.tool.questions")} dismissed
{i18n.t("ui.messagePart.questions.dismissed")}
</span>
</div>
)

View File

@@ -1,4 +1,5 @@
import { createSignal, onCleanup, onMount, splitProps, type ComponentProps, Show, mergeProps } from "solid-js"
import { useI18n } from "../context/i18n"
export interface ScrollViewProps extends ComponentProps<"div"> {
viewportRef?: (el: HTMLDivElement) => void
@@ -6,6 +7,7 @@ export interface ScrollViewProps extends ComponentProps<"div"> {
}
export function ScrollView(props: ScrollViewProps) {
const i18n = useI18n()
const merged = mergeProps({ orientation: "vertical" }, props)
const [local, events, rest] = splitProps(
merged,
@@ -188,7 +190,7 @@ export function ScrollView(props: ScrollViewProps) {
onClick={events.onClick as any}
tabIndex={0}
role="region"
aria-label="scrollable content"
aria-label={i18n.t("ui.scrollView.ariaLabel")}
onKeyDown={(e) => {
onKeyDown(e)
if (typeof events.onKeyDown === "function") events.onKeyDown(e as any)

View File

@@ -16,18 +16,8 @@ import { useFileComponent } from "../context/file"
import { useI18n } from "../context/i18n"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { checksum } from "@opencode-ai/util/encode"
import {
createEffect,
createMemo,
createSignal,
For,
Match,
onCleanup,
Show,
Switch,
untrack,
type JSX,
} from "solid-js"
import { createEffect, createMemo, createSignal, For, Match, Show, Switch, untrack, type JSX } from "solid-js"
import { onCleanup } from "solid-js"
import { createStore } from "solid-js/store"
import { type FileContent, type FileDiff } from "@opencode-ai/sdk/v2"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
@@ -191,6 +181,15 @@ export const SessionReview = (props: SessionReviewProps) => {
highlightedFile = undefined
}
const openFileLabel = () => i18n.t("ui.sessionReview.openFile")
const selectionLabel = (range: SelectedLineRange) => {
const start = Math.min(range.start, range.end)
const end = Math.max(range.start, range.end)
if (start === end) return i18n.t("ui.sessionReview.selection.line", { line: start })
return i18n.t("ui.sessionReview.selection.lines", { start, end })
}
const focusSearch = () => {
if (!hasDiffs()) return
setSearchOpen(true)
@@ -475,7 +474,8 @@ export const SessionReview = (props: SessionReviewProps) => {
const wrapper = anchors.get(focus.file)
const anchor = wrapper?.querySelector(`[data-comment-id="${focus.id}"]`)
const ready = anchor instanceof HTMLElement
const ready =
anchor instanceof HTMLElement && anchor.style.pointerEvents !== "none" && anchor.style.opacity !== "0"
const target = ready ? anchor : wrapper
if (!target) {
@@ -751,11 +751,11 @@ export const SessionReview = (props: SessionReviewProps) => {
</Show>
<span data-slot="session-review-filename">{getFilename(file)}</span>
<Show when={props.onViewFile}>
<Tooltip value="Open file" placement="top" gutter={4}>
<Tooltip value={openFileLabel()} placement="top" gutter={4}>
<button
data-slot="session-review-view-button"
type="button"
aria-label="Open file"
aria-label={openFileLabel()}
onClick={(e) => {
e.stopPropagation()
props.onViewFile?.(file)