diff options
| author | Adam <[email protected]> | 2026-03-13 06:48:38 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-13 06:48:38 -0500 |
| commit | 05cb3c87ca387be41aceb5ccad978c6848a56f70 (patch) | |
| tree | 2b592d2aa90d0fdb7ea72aa392507e2277b92ba5 /packages/ui | |
| parent | 270cb0b8b4265ac0965ac8b94a58a3bca86fa558 (diff) | |
| download | opencode-05cb3c87ca387be41aceb5ccad978c6848a56f70.tar.gz opencode-05cb3c87ca387be41aceb5ccad978c6848a56f70.zip | |
chore(app): i18n sync (#17283)
Diffstat (limited to 'packages/ui')
23 files changed, 248 insertions, 26 deletions
diff --git a/packages/ui/src/components/basic-tool.tsx b/packages/ui/src/components/basic-tool.tsx index 3f009f4e0..0b2c1e1ce 100644 --- a/packages/ui/src/components/basic-tool.tsx +++ b/packages/ui/src/components/basic-tool.tsx @@ -1,5 +1,6 @@ import { createEffect, For, Match, on, onCleanup, Show, Switch, type JSX } from "solid-js" import { animate, type AnimationPlaybackControls } from "motion" +import { useI18n } from "../context/i18n" import { createStore } from "solid-js/store" import { Collapsible } from "./collapsible" import type { IconProps } from "./icon" @@ -233,12 +234,14 @@ export function GenericTool(props: { hideDetails?: boolean input?: Record<string, unknown> }) { + const i18n = useI18n() + return ( <BasicTool icon="mcp" status={props.status} trigger={{ - title: `Called \`${props.tool}\``, + title: i18n.t("ui.basicTool.called", { tool: props.tool }), subtitle: label(props.input), args: args(props.input), }} diff --git a/packages/ui/src/components/file-search.tsx b/packages/ui/src/components/file-search.tsx index d83fdb16a..244e9c273 100644 --- a/packages/ui/src/components/file-search.tsx +++ b/packages/ui/src/components/file-search.tsx @@ -1,4 +1,5 @@ import { Portal } from "solid-js/web" +import { useI18n } from "../context/i18n" import { Icon } from "./icon" export function FileSearchBar(props: { @@ -13,6 +14,8 @@ export function FileSearchBar(props: { onPrev: () => void onNext: () => void }) { + const i18n = useI18n() + return ( <Portal> <div @@ -26,7 +29,7 @@ export function FileSearchBar(props: { <Icon name="magnifying-glass" size="small" class="text-text-weak shrink-0" /> <input ref={props.setInput} - placeholder="Find" + placeholder={i18n.t("ui.fileSearch.placeholder")} value={props.query()} class="w-40 bg-transparent outline-none text-14-regular text-text-strong placeholder:text-text-weak" onInput={(e) => props.onInput(e.currentTarget.value)} @@ -40,7 +43,7 @@ export function FileSearchBar(props: { type="button" class="size-6 grid place-items-center rounded text-text-weak hover:bg-surface-base-hover hover:text-text-strong disabled:opacity-40 disabled:pointer-events-none" disabled={props.count() === 0} - aria-label="Previous match" + aria-label={i18n.t("ui.fileSearch.previousMatch")} onClick={props.onPrev} > <Icon name="chevron-down" size="small" class="rotate-180" /> @@ -49,7 +52,7 @@ export function FileSearchBar(props: { type="button" class="size-6 grid place-items-center rounded text-text-weak hover:bg-surface-base-hover hover:text-text-strong disabled:opacity-40 disabled:pointer-events-none" disabled={props.count() === 0} - aria-label="Next match" + aria-label={i18n.t("ui.fileSearch.nextMatch")} onClick={props.onNext} > <Icon name="chevron-down" size="small" /> @@ -58,7 +61,7 @@ export function FileSearchBar(props: { <button type="button" class="size-6 grid place-items-center rounded text-text-weak hover:bg-surface-base-hover hover:text-text-strong" - aria-label="Close search" + aria-label={i18n.t("ui.fileSearch.close")} onClick={props.onClose} > <Icon name="close-small" size="small" /> diff --git a/packages/ui/src/components/line-comment-annotations.tsx b/packages/ui/src/components/line-comment-annotations.tsx index 3505487eb..a4870074d 100644 --- a/packages/ui/src/components/line-comment-annotations.tsx +++ b/packages/ui/src/components/line-comment-annotations.tsx @@ -2,6 +2,7 @@ import { type DiffLineAnnotation, type SelectedLineRange } from "@pierre/diffs" import { createEffect, createMemo, createSignal, onCleanup, Show, type Accessor, type JSX } from "solid-js" import { createStore } from "solid-js/store" import { render as renderSolid } from "solid-js/web" +import { useI18n } from "../context/i18n" import { createHoverCommentUtility } from "../pierre/comment-hover" import { cloneSelectedLineRange, formatSelectedLineLabel, lineInSelectedRange } from "../pierre/selection-bridge" import { LineComment, LineCommentEditor } from "./line-comment" @@ -341,6 +342,7 @@ export function createLineCommentController<T extends LineCommentShape>( export function createLineCommentController<T extends LineCommentShape>( props: LineCommentControllerProps<T> | LineCommentControllerWithSideProps<T>, ) { + const i18n = useI18n() const note = createLineCommentState<string>(props.state) const annotations = @@ -376,7 +378,7 @@ export function createLineCommentController<T extends LineCommentShape>( return note.isOpen(comment.id) || note.isEditing(comment.id) }, comment: comment.comment, - selection: formatSelectedLineLabel(comment.selection), + selection: formatSelectedLineLabel(comment.selection, i18n.t), get actions() { return props.renderCommentActions?.(comment, { edit, remove }) }, @@ -386,7 +388,7 @@ export function createLineCommentController<T extends LineCommentShape>( get value() { return note.draft() }, - selection: formatSelectedLineLabel(comment.selection), + selection: formatSelectedLineLabel(comment.selection, i18n.t), onInput: note.setDraft, onCancel: note.cancelDraft, onSubmit: (value: string) => { @@ -412,7 +414,7 @@ export function createLineCommentController<T extends LineCommentShape>( get value() { return note.draft() }, - selection: formatSelectedLineLabel(range), + selection: formatSelectedLineLabel(range, i18n.t), onInput: note.setDraft, onCancel: note.cancelDraft, onSubmit: (comment) => { diff --git a/packages/ui/src/components/message-part.tsx b/packages/ui/src/components/message-part.tsx index a89d97272..b580998b6 100644 --- a/packages/ui/src/components/message-part.tsx +++ b/packages/ui/src/components/message-part.tsx @@ -322,7 +322,7 @@ export function getToolInfo(tool: string, input: any = {}): ToolInfo { case "skill": return { icon: "brain", - title: input.name || "skill", + title: input.name || i18n.t("ui.tool.skill"), } default: return { @@ -924,15 +924,12 @@ export function UserMessageDisplay(props: { message: UserMessage; parts: PartTyp const match = data.store.provider?.all?.find((p) => p.id === providerID) return match?.models?.[modelID]?.name ?? modelID }) + const timefmt = createMemo(() => new Intl.DateTimeFormat(i18n.locale(), { timeStyle: "short" })) const stamp = createMemo(() => { const created = props.message.time?.created if (typeof created !== "number") return "" - const date = new Date(created) - const hours = date.getHours() - const hour12 = hours % 12 || 12 - const minute = String(date.getMinutes()).padStart(2, "0") - return `${hour12}:${minute} ${hours < 12 ? "AM" : "PM"}` + return timefmt().format(created) }) const metaHead = createMemo(() => { @@ -1318,6 +1315,7 @@ PART_MAPPING["compaction"] = function CompactionPartDisplay() { PART_MAPPING["text"] = function TextPartDisplay(props) { const data = useData() const i18n = useI18n() + const numfmt = createMemo(() => new Intl.NumberFormat(i18n.locale())) const part = () => props.part as TextPart const interrupted = createMemo( () => @@ -1343,10 +1341,13 @@ PART_MAPPING["text"] = function TextPartDisplay(props) { : -1 if (!(ms >= 0)) return "" const total = Math.round(ms / 1000) - if (total < 60) return `${total}s` + if (total < 60) return i18n.t("ui.message.duration.seconds", { count: numfmt().format(total) }) const minutes = Math.floor(total / 60) const seconds = total % 60 - return `${minutes}m ${seconds}s` + return i18n.t("ui.message.duration.minutesSeconds", { + minutes: numfmt().format(minutes), + seconds: numfmt().format(seconds), + }) }) const meta = createMemo(() => { @@ -2206,7 +2207,8 @@ ToolRegistry.register({ ToolRegistry.register({ name: "skill", render(props) { - const title = createMemo(() => props.input.name || "skill") + const i18n = useI18n() + const title = createMemo(() => props.input.name || i18n.t("ui.tool.skill")) const running = createMemo(() => props.status === "pending" || props.status === "running") const titleContent = () => <TextShimmer text={title()} active={running()} /> diff --git a/packages/ui/src/components/tool-error-card.tsx b/packages/ui/src/components/tool-error-card.tsx index 0c99924de..038870d38 100644 --- a/packages/ui/src/components/tool-error-card.tsx +++ b/packages/ui/src/components/tool-error-card.tsx @@ -30,7 +30,7 @@ export function ToolErrorCard(props: ToolErrorCardProps) { list: "ui.tool.list", glob: "ui.tool.glob", grep: "ui.tool.grep", - task: "Task", + task: "ui.tool.task", webfetch: "ui.tool.webfetch", websearch: "ui.tool.websearch", codesearch: "ui.tool.codesearch", @@ -54,10 +54,10 @@ export function ToolErrorCard(props: ToolErrorCardProps) { const subtitle = createMemo(() => { if (split.subtitle) return split.subtitle const parts = tail().split(": ") - if (parts.length <= 1) return "Failed" + if (parts.length <= 1) return i18n.t("ui.toolErrorCard.failed") const head = (parts[0] ?? "").trim() - if (!head) return "Failed" - return head[0] ? head[0].toUpperCase() + head.slice(1) : "Failed" + if (!head) return i18n.t("ui.toolErrorCard.failed") + return head[0] ? head[0].toUpperCase() + head.slice(1) : i18n.t("ui.toolErrorCard.failed") }) const body = createMemo(() => { @@ -116,7 +116,11 @@ export function ToolErrorCard(props: ToolErrorCardProps) { <div data-slot="tool-error-card-content"> <Show when={open()}> <div data-slot="tool-error-card-copy"> - <Tooltip value={copied() ? i18n.t("ui.message.copied") : "Copy error"} placement="top" gutter={4}> + <Tooltip + value={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.toolErrorCard.copyError")} + placement="top" + gutter={4} + > <IconButton icon={copied() ? "check" : "copy"} size="normal" @@ -126,7 +130,7 @@ export function ToolErrorCard(props: ToolErrorCardProps) { e.stopPropagation() copy() }} - aria-label={copied() ? i18n.t("ui.message.copied") : "Copy error"} + aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.toolErrorCard.copyError")} /> </Tooltip> </div> diff --git a/packages/ui/src/i18n/ar.ts b/packages/ui/src/i18n/ar.ts index 475496df0..f3e321ce5 100644 --- a/packages/ui/src/i18n/ar.ts +++ b/packages/ui/src/i18n/ar.ts @@ -145,4 +145,16 @@ export const dict = { "ui.question.multiHint": "حدد كل ما ينطبق", "ui.question.singleHint": "حدد إجابة واحدة", "ui.question.custom.placeholder": "اكتب إجابتك...", + + "ui.fileSearch.placeholder": "بحث", + "ui.fileSearch.previousMatch": "المطابقة السابقة", + "ui.fileSearch.nextMatch": "المطابقة التالية", + "ui.fileSearch.close": "إغلاق البحث", + "ui.tool.task": "مهمة", + "ui.tool.skill": "مهارة", + "ui.basicTool.called": "تم استدعاء `{{tool}}`", + "ui.toolErrorCard.failed": "فشل", + "ui.toolErrorCard.copyError": "نسخ الخطأ", + "ui.message.duration.seconds": "{{count}}ث", + "ui.message.duration.minutesSeconds": "{{minutes}}د {{seconds}}ث", } diff --git a/packages/ui/src/i18n/br.ts b/packages/ui/src/i18n/br.ts index 8e68d0fef..d0ba67871 100644 --- a/packages/ui/src/i18n/br.ts +++ b/packages/ui/src/i18n/br.ts @@ -145,4 +145,16 @@ export const dict = { "ui.question.multiHint": "Selecione todas que se aplicam", "ui.question.singleHint": "Selecione uma resposta", "ui.question.custom.placeholder": "Digite sua resposta...", + + "ui.fileSearch.placeholder": "Localizar", + "ui.fileSearch.previousMatch": "Ocorrência anterior", + "ui.fileSearch.nextMatch": "Próxima ocorrência", + "ui.fileSearch.close": "Fechar busca", + "ui.tool.task": "Tarefa", + "ui.tool.skill": "Habilidade", + "ui.basicTool.called": "Chamou `{{tool}}`", + "ui.toolErrorCard.failed": "Falhou", + "ui.toolErrorCard.copyError": "Copiar erro", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/bs.ts b/packages/ui/src/i18n/bs.ts index 60fa9c789..3707c7139 100644 --- a/packages/ui/src/i18n/bs.ts +++ b/packages/ui/src/i18n/bs.ts @@ -149,4 +149,16 @@ export const dict = { "ui.question.multiHint": "Odaberi sve što važi", "ui.question.singleHint": "Odaberi jedan odgovor", "ui.question.custom.placeholder": "Unesi svoj odgovor...", + + "ui.fileSearch.placeholder": "Pronađi", + "ui.fileSearch.previousMatch": "Prethodno", + "ui.fileSearch.nextMatch": "Sljedeće", + "ui.fileSearch.close": "Zatvori pretragu", + "ui.tool.task": "Zadatak", + "ui.tool.skill": "Vještina", + "ui.basicTool.called": "Pozvan `{{tool}}`", + "ui.toolErrorCard.failed": "Neuspješno", + "ui.toolErrorCard.copyError": "Kopiraj grešku", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } satisfies Partial<Record<Keys, string>> diff --git a/packages/ui/src/i18n/da.ts b/packages/ui/src/i18n/da.ts index 74e06b99d..60e3fb30f 100644 --- a/packages/ui/src/i18n/da.ts +++ b/packages/ui/src/i18n/da.ts @@ -144,4 +144,16 @@ export const dict = { "ui.question.multiHint": "Vælg alle der gælder", "ui.question.singleHint": "Vælg ét svar", "ui.question.custom.placeholder": "Skriv dit svar...", + + "ui.fileSearch.placeholder": "Find", + "ui.fileSearch.previousMatch": "Forrige match", + "ui.fileSearch.nextMatch": "Næste match", + "ui.fileSearch.close": "Luk søgning", + "ui.tool.task": "Opgave", + "ui.tool.skill": "Færdighed", + "ui.basicTool.called": "Kaldte `{{tool}}`", + "ui.toolErrorCard.failed": "Fejlede", + "ui.toolErrorCard.copyError": "Kopier fejl", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/de.ts b/packages/ui/src/i18n/de.ts index 296417597..7fab33f56 100644 --- a/packages/ui/src/i18n/de.ts +++ b/packages/ui/src/i18n/de.ts @@ -150,4 +150,16 @@ export const dict = { "ui.question.multiHint": "Alle zutreffenden auswählen", "ui.question.singleHint": "Eine Antwort auswählen", "ui.question.custom.placeholder": "Geben Sie Ihre Antwort ein...", + + "ui.fileSearch.placeholder": "Suchen", + "ui.fileSearch.previousMatch": "Vorheriges Ergebnis", + "ui.fileSearch.nextMatch": "Nächstes Ergebnis", + "ui.fileSearch.close": "Suche schließen", + "ui.tool.task": "Aufgabe", + "ui.tool.skill": "Fähigkeit", + "ui.basicTool.called": "`{{tool}}` aufgerufen", + "ui.toolErrorCard.failed": "Fehlgeschlagen", + "ui.toolErrorCard.copyError": "Fehler kopieren", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } satisfies Partial<Record<Keys, string>> diff --git a/packages/ui/src/i18n/en.ts b/packages/ui/src/i18n/en.ts index 2b41bc03d..197dca445 100644 --- a/packages/ui/src/i18n/en.ts +++ b/packages/ui/src/i18n/en.ts @@ -80,6 +80,11 @@ export const dict: Record<string, string> = { "ui.list.emptyWithFilter.prefix": "No results for", "ui.list.emptyWithFilter.suffix": "", + "ui.fileSearch.placeholder": "Find", + "ui.fileSearch.previousMatch": "Previous match", + "ui.fileSearch.nextMatch": "Next match", + "ui.fileSearch.close": "Close search", + "ui.messageNav.newMessage": "New message", "ui.textField.copyToClipboard": "Copy to clipboard", @@ -94,6 +99,7 @@ export const dict: Record<string, string> = { "ui.tool.list": "List", "ui.tool.glob": "Glob", "ui.tool.grep": "Grep", + "ui.tool.task": "Task", "ui.tool.webfetch": "Webfetch", "ui.tool.websearch": "Web Search", "ui.tool.codesearch": "Code Search", @@ -104,6 +110,11 @@ export const dict: Record<string, string> = { "ui.tool.questions": "Questions", "ui.tool.agent": "{{type}} Agent", "ui.tool.agent.default": "Agent", + "ui.tool.skill": "Skill", + + "ui.basicTool.called": "Called `{{tool}}`", + "ui.toolErrorCard.failed": "Failed", + "ui.toolErrorCard.copyError": "Copy error", "ui.common.file.one": "file", "ui.common.file.other": "files", @@ -131,6 +142,8 @@ export const dict: Record<string, string> = { "ui.message.revertMessage": "Revert message", "ui.message.copyResponse": "Copy response", "ui.message.copied": "Copied", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", "ui.message.interrupted": "Interrupted", "ui.message.queued": "Queued", "ui.message.attachment.alt": "attachment", diff --git a/packages/ui/src/i18n/es.ts b/packages/ui/src/i18n/es.ts index 6496c05db..77781e460 100644 --- a/packages/ui/src/i18n/es.ts +++ b/packages/ui/src/i18n/es.ts @@ -145,4 +145,16 @@ export const dict = { "ui.question.multiHint": "Selecciona todas las que correspondan", "ui.question.singleHint": "Selecciona una respuesta", "ui.question.custom.placeholder": "Escribe tu respuesta...", + + "ui.fileSearch.placeholder": "Buscar", + "ui.fileSearch.previousMatch": "Anterior", + "ui.fileSearch.nextMatch": "Siguiente", + "ui.fileSearch.close": "Cerrar búsqueda", + "ui.tool.task": "Tarea", + "ui.tool.skill": "Habilidad", + "ui.basicTool.called": "Llamado `{{tool}}`", + "ui.toolErrorCard.failed": "Falló", + "ui.toolErrorCard.copyError": "Copiar error", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/fr.ts b/packages/ui/src/i18n/fr.ts index e278d0693..78a8ecf75 100644 --- a/packages/ui/src/i18n/fr.ts +++ b/packages/ui/src/i18n/fr.ts @@ -145,4 +145,16 @@ export const dict = { "ui.question.multiHint": "Sélectionnez tout ce qui s'applique", "ui.question.singleHint": "Sélectionnez une réponse", "ui.question.custom.placeholder": "Tapez votre réponse...", + + "ui.fileSearch.placeholder": "Rechercher", + "ui.fileSearch.previousMatch": "Précédent", + "ui.fileSearch.nextMatch": "Suivant", + "ui.fileSearch.close": "Fermer la recherche", + "ui.tool.task": "Tâche", + "ui.tool.skill": "Compétence", + "ui.basicTool.called": "Appelé `{{tool}}`", + "ui.toolErrorCard.failed": "Échoué", + "ui.toolErrorCard.copyError": "Copier l'erreur", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/ja.ts b/packages/ui/src/i18n/ja.ts index b133a3282..59cf33ad2 100644 --- a/packages/ui/src/i18n/ja.ts +++ b/packages/ui/src/i18n/ja.ts @@ -144,4 +144,16 @@ export const dict = { "ui.question.multiHint": "該当するものをすべて選択", "ui.question.singleHint": "1 つ選択", "ui.question.custom.placeholder": "回答を入力...", + + "ui.fileSearch.placeholder": "検索", + "ui.fileSearch.previousMatch": "前の一致", + "ui.fileSearch.nextMatch": "次の一致", + "ui.fileSearch.close": "検索を閉じる", + "ui.tool.task": "タスク", + "ui.tool.skill": "スキル", + "ui.basicTool.called": "`{{tool}}` を呼び出しました", + "ui.toolErrorCard.failed": "失敗", + "ui.toolErrorCard.copyError": "エラーをコピー", + "ui.message.duration.seconds": "{{count}}秒", + "ui.message.duration.minutesSeconds": "{{minutes}}分 {{seconds}}秒", } diff --git a/packages/ui/src/i18n/ko.ts b/packages/ui/src/i18n/ko.ts index 3e7af7140..1fed9e860 100644 --- a/packages/ui/src/i18n/ko.ts +++ b/packages/ui/src/i18n/ko.ts @@ -145,4 +145,16 @@ export const dict = { "ui.question.multiHint": "해당하는 항목 모두 선택", "ui.question.singleHint": "하나의 답변을 선택", "ui.question.custom.placeholder": "답변 입력...", + + "ui.fileSearch.placeholder": "찾기", + "ui.fileSearch.previousMatch": "이전 항목", + "ui.fileSearch.nextMatch": "다음 항목", + "ui.fileSearch.close": "검색 닫기", + "ui.tool.task": "작업", + "ui.tool.skill": "스킬", + "ui.basicTool.called": "`{{tool}}` 호출됨", + "ui.toolErrorCard.failed": "실패", + "ui.toolErrorCard.copyError": "오류 복사", + "ui.message.duration.seconds": "{{count}}초", + "ui.message.duration.minutesSeconds": "{{minutes}}분 {{seconds}}초", } diff --git a/packages/ui/src/i18n/no.ts b/packages/ui/src/i18n/no.ts index 0c9fc82e5..f3a808658 100644 --- a/packages/ui/src/i18n/no.ts +++ b/packages/ui/src/i18n/no.ts @@ -148,4 +148,16 @@ export const dict: Record<Keys, string> = { "ui.question.multiHint": "Velg alle som gjelder", "ui.question.singleHint": "Velg ett svar", "ui.question.custom.placeholder": "Skriv svaret ditt...", + + "ui.fileSearch.placeholder": "Finn", + "ui.fileSearch.previousMatch": "Forrige treff", + "ui.fileSearch.nextMatch": "Neste treff", + "ui.fileSearch.close": "Lukk søk", + "ui.tool.task": "Oppgave", + "ui.tool.skill": "Ferdighet", + "ui.basicTool.called": "Kalte `{{tool}}`", + "ui.toolErrorCard.failed": "Mislyktes", + "ui.toolErrorCard.copyError": "Kopier feil", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/pl.ts b/packages/ui/src/i18n/pl.ts index e63622a83..ea05e2f0e 100644 --- a/packages/ui/src/i18n/pl.ts +++ b/packages/ui/src/i18n/pl.ts @@ -144,4 +144,16 @@ export const dict = { "ui.question.multiHint": "Zaznacz wszystkie pasujące", "ui.question.singleHint": "Wybierz jedną odpowiedź", "ui.question.custom.placeholder": "Wpisz swoją odpowiedź...", + + "ui.fileSearch.placeholder": "Szukaj", + "ui.fileSearch.previousMatch": "Poprzednie", + "ui.fileSearch.nextMatch": "Następne", + "ui.fileSearch.close": "Zamknij wyszukiwanie", + "ui.tool.task": "Zadanie", + "ui.tool.skill": "Umiejętność", + "ui.basicTool.called": "Wywołano `{{tool}}`", + "ui.toolErrorCard.failed": "Błąd", + "ui.toolErrorCard.copyError": "Kopiuj błąd", + "ui.message.duration.seconds": "{{count}}s", + "ui.message.duration.minutesSeconds": "{{minutes}}m {{seconds}}s", } diff --git a/packages/ui/src/i18n/ru.ts b/packages/ui/src/i18n/ru.ts index b8c7a4a1f..9ae49bd9e 100644 --- a/packages/ui/src/i18n/ru.ts +++ b/packages/ui/src/i18n/ru.ts @@ -144,4 +144,16 @@ export const dict = { "ui.question.multiHint": "Выберите все подходящие", "ui.question.singleHint": "Выберите один ответ", "ui.question.custom.placeholder": "Введите ваш ответ...", + + "ui.fileSearch.placeholder": "Найти", + "ui.fileSearch.previousMatch": "Предыдущее", + "ui.fileSearch.nextMatch": "Следующее", + "ui.fileSearch.close": "Закрыть поиск", + "ui.tool.task": "Задача", + "ui.tool.skill": "Навык", + "ui.basicTool.called": "Вызван `{{tool}}`", + "ui.toolErrorCard.failed": "Ошибка", + "ui.toolErrorCard.copyError": "Скопировать ошибку", + "ui.message.duration.seconds": "{{count}}с", + "ui.message.duration.minutesSeconds": "{{minutes}}м {{seconds}}с", } diff --git a/packages/ui/src/i18n/th.ts b/packages/ui/src/i18n/th.ts index 88236b644..8719596fe 100644 --- a/packages/ui/src/i18n/th.ts +++ b/packages/ui/src/i18n/th.ts @@ -146,4 +146,16 @@ export const dict = { "ui.question.multiHint": "เลือกทั้งหมดที่ใช้", "ui.question.singleHint": "เลือกหนึ่งคำตอบ", "ui.question.custom.placeholder": "พิมพ์คำตอบของคุณ...", + + "ui.fileSearch.placeholder": "ค้นหา", + "ui.fileSearch.previousMatch": "ก่อนหน้า", + "ui.fileSearch.nextMatch": "ถัดไป", + "ui.fileSearch.close": "ปิดการค้นหา", + "ui.tool.task": "งาน", + "ui.tool.skill": "ทักษะ", + "ui.basicTool.called": "เรียกใช้ `{{tool}}`", + "ui.toolErrorCard.failed": "ล้มเหลว", + "ui.toolErrorCard.copyError": "คัดลอกข้อผิดพลาด", + "ui.message.duration.seconds": "{{count}}วิ", + "ui.message.duration.minutesSeconds": "{{minutes}}นาที {{seconds}}วิ", } diff --git a/packages/ui/src/i18n/tr.ts b/packages/ui/src/i18n/tr.ts index ff9de61b5..a17ba331e 100644 --- a/packages/ui/src/i18n/tr.ts +++ b/packages/ui/src/i18n/tr.ts @@ -151,4 +151,16 @@ export const dict = { "ui.question.multiHint": "Geçerli tüm cevapları seçin", "ui.question.singleHint": "Bir cevap seçin", "ui.question.custom.placeholder": "Cevabınızı yazın...", + + "ui.fileSearch.placeholder": "Bul", + "ui.fileSearch.previousMatch": "Önceki", + "ui.fileSearch.nextMatch": "Sonraki", + "ui.fileSearch.close": "Aramayı kapat", + "ui.tool.task": "Görev", + "ui.tool.skill": "Yetenek", + "ui.basicTool.called": "`{{tool}}` çağrıldı", + "ui.toolErrorCard.failed": "Başarısız", + "ui.toolErrorCard.copyError": "Hatayı kopyala", + "ui.message.duration.seconds": "{{count}}sn", + "ui.message.duration.minutesSeconds": "{{minutes}}dk {{seconds}}sn", } satisfies Partial<Record<Keys, string>> diff --git a/packages/ui/src/i18n/zh.ts b/packages/ui/src/i18n/zh.ts index aaf17eee8..788cb3cfc 100644 --- a/packages/ui/src/i18n/zh.ts +++ b/packages/ui/src/i18n/zh.ts @@ -149,4 +149,16 @@ export const dict = { "ui.question.multiHint": "可多选", "ui.question.singleHint": "选择一个答案", "ui.question.custom.placeholder": "输入你的答案...", + + "ui.fileSearch.placeholder": "查找", + "ui.fileSearch.previousMatch": "上一个", + "ui.fileSearch.nextMatch": "下一个", + "ui.fileSearch.close": "关闭搜索", + "ui.tool.task": "任务", + "ui.tool.skill": "技能", + "ui.basicTool.called": "调用了 `{{tool}}`", + "ui.toolErrorCard.failed": "失败", + "ui.toolErrorCard.copyError": "复制错误", + "ui.message.duration.seconds": "{{count}}秒", + "ui.message.duration.minutesSeconds": "{{minutes}}分 {{seconds}}秒", } satisfies Partial<Record<Keys, string>> diff --git a/packages/ui/src/i18n/zht.ts b/packages/ui/src/i18n/zht.ts index b8a9fa799..b4adeab79 100644 --- a/packages/ui/src/i18n/zht.ts +++ b/packages/ui/src/i18n/zht.ts @@ -149,4 +149,16 @@ export const dict = { "ui.question.multiHint": "可多選", "ui.question.singleHint": "選擇一個答案", "ui.question.custom.placeholder": "輸入你的答案...", + + "ui.fileSearch.placeholder": "搜尋", + "ui.fileSearch.previousMatch": "上一個", + "ui.fileSearch.nextMatch": "下一個", + "ui.fileSearch.close": "關閉搜尋", + "ui.tool.task": "任務", + "ui.tool.skill": "技能", + "ui.basicTool.called": "呼叫了 `{{tool}}`", + "ui.toolErrorCard.failed": "失敗", + "ui.toolErrorCard.copyError": "複製錯誤", + "ui.message.duration.seconds": "{{count}}秒", + "ui.message.duration.minutesSeconds": "{{minutes}}分 {{seconds}}秒", } satisfies Partial<Record<Keys, string>> diff --git a/packages/ui/src/pierre/selection-bridge.ts b/packages/ui/src/pierre/selection-bridge.ts index d493ead3d..4055ec087 100644 --- a/packages/ui/src/pierre/selection-bridge.ts +++ b/packages/ui/src/pierre/selection-bridge.ts @@ -1,14 +1,17 @@ import { type SelectedLineRange } from "@pierre/diffs" +type SelectionKey = "ui.sessionReview.selection.line" | "ui.sessionReview.selection.lines" +type SelectionVars = Record<string, string | number> + type PointerMode = "none" | "text" | "numbers" type Side = SelectedLineRange["side"] type LineSpan = Pick<SelectedLineRange, "start" | "end"> -export function formatSelectedLineLabel(range: LineSpan) { +export function formatSelectedLineLabel(range: LineSpan, t: (key: SelectionKey, params: SelectionVars) => string) { const start = Math.min(range.start, range.end) const end = Math.max(range.start, range.end) - if (start === end) return `line ${start}` - return `lines ${start}-${end}` + if (start === end) return t("ui.sessionReview.selection.line", { line: start }) + return t("ui.sessionReview.selection.lines", { start, end }) } export function previewSelectedLines(source: string, range: LineSpan) { |
