mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-22 19:03:33 +00:00
feat(desktop): improve file comments in session timeline (#36845)
Co-authored-by: LukeParkerDev <10430890+Hona@users.noreply.github.com>
This commit is contained in:
parent
21f8184c58
commit
dedb4133dc
23 changed files with 275 additions and 116 deletions
|
|
@ -133,10 +133,6 @@
|
|||
align-items: flex-end;
|
||||
}
|
||||
|
||||
[data-slot="user-message-attachments"] + [data-slot="user-message-body"] {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
[data-slot="user-message-text"] {
|
||||
display: inline-block;
|
||||
white-space: pre-wrap;
|
||||
|
|
@ -1324,10 +1320,61 @@
|
|||
}
|
||||
}
|
||||
|
||||
body[data-new-layout] [data-component="user-message"] {
|
||||
font-weight: 440;
|
||||
|
||||
[data-slot="user-message-text"] {
|
||||
background: var(--v2-background-bg-layer-01);
|
||||
}
|
||||
|
||||
[data-slot="user-message-comments"] {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
width: min(320px, 82%);
|
||||
margin-left: auto;
|
||||
|
||||
&[data-bounded] {
|
||||
width: 318px;
|
||||
max-width: 100%;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
[data-component="tooltip-v2-trigger"] {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
[data-component="button-v2"] {
|
||||
font-family: var(--v2-font-family-sans, "Inter", sans-serif);
|
||||
font-weight: 530;
|
||||
font-variation-settings: "wght" 530, "slnt" 0;
|
||||
}
|
||||
}
|
||||
|
||||
[data-slot="user-message-body"] + [data-slot="user-message-attachments"],
|
||||
[data-slot="user-message-comments"] + [data-slot="user-message-attachments"] {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
[data-slot="user-message-text"][data-comments] {
|
||||
width: 342px;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
[data-color-scheme="light"] body[data-new-layout] [data-component="user-message"] [data-slot="user-message-text"] {
|
||||
background: var(--v2-background-bg-layer-02);
|
||||
}
|
||||
|
||||
body:not([data-new-layout]) {
|
||||
[data-component="user-message"] {
|
||||
color: var(--text-strong);
|
||||
|
||||
[data-slot="user-message-attachments"] + [data-slot="user-message-body"] {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
[data-slot="user-message-attachment"] {
|
||||
background: var(--surface-weak);
|
||||
border: 1px solid var(--border-weak-base);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ import { Tooltip } from "@opencode-ai/ui/tooltip"
|
|||
import { IconButton } from "@opencode-ai/ui/icon-button"
|
||||
import { Icon as IconV2 } from "@opencode-ai/ui/v2/icon"
|
||||
import { IconButtonV2 } from "@opencode-ai/ui/v2/icon-button-v2"
|
||||
import { ButtonV2 } from "@opencode-ai/ui/v2/button-v2"
|
||||
import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2"
|
||||
import { Spinner } from "@opencode-ai/ui/spinner"
|
||||
import { TextShimmer } from "@opencode-ai/ui/text-shimmer"
|
||||
|
|
@ -1172,6 +1173,36 @@ export function ContextToolGroup(props: {
|
|||
)
|
||||
}
|
||||
|
||||
function UserMessageComments(props: { comments: UserMessageComment[]; bounded: boolean }) {
|
||||
const i18n = useI18n()
|
||||
const [state, setState] = createStore({ expanded: false })
|
||||
const comments = createMemo(() =>
|
||||
props.bounded && !state.expanded ? props.comments.slice(0, 5) : props.comments,
|
||||
)
|
||||
|
||||
return (
|
||||
<div data-slot="user-message-comments" data-bounded={props.bounded ? "true" : undefined}>
|
||||
<For each={comments()}>
|
||||
{(comment) => (
|
||||
<CommentCardV2
|
||||
comment={comment.comment}
|
||||
path={comment.path}
|
||||
selection={comment.selection}
|
||||
title={comment.comment}
|
||||
tooltip
|
||||
wide
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
<Show when={props.bounded && props.comments.length > 5 && !state.expanded}>
|
||||
<ButtonV2 size="small" variant="ghost-muted" onClick={() => setState("expanded", true)}>
|
||||
{i18n.t("ui.common.showMore")}
|
||||
</ButtonV2>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function UserMessageDisplay(props: {
|
||||
message: UserMessage
|
||||
parts: PartType[]
|
||||
|
|
@ -1255,107 +1286,114 @@ export function UserMessageDisplay(props: {
|
|||
.finally(() => setState("busy", false))
|
||||
}
|
||||
|
||||
const renderAttachments = () => (
|
||||
<Show when={attachments().length > 0}>
|
||||
<div data-slot="user-message-attachments">
|
||||
<For each={attachments()}>
|
||||
{(file) => {
|
||||
const type = kind(file)
|
||||
const name = file.filename ?? i18n.t("ui.message.attachment.alt")
|
||||
|
||||
return (
|
||||
<Show
|
||||
when={newLayout() && type === "file"}
|
||||
fallback={
|
||||
<div
|
||||
data-slot="user-message-attachment"
|
||||
data-type={type}
|
||||
data-clickable={type === "image" ? "true" : undefined}
|
||||
title={type === "file" ? name : undefined}
|
||||
onClick={() => {
|
||||
if (type === "image") openImagePreview(file.url, name)
|
||||
}}
|
||||
>
|
||||
<Show
|
||||
when={type === "image"}
|
||||
fallback={
|
||||
<div data-slot="user-message-attachment-file">
|
||||
<FileIcon node={{ path: name, type: "file" }} />
|
||||
<span data-slot="user-message-attachment-name">{name}</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<img data-slot="user-message-attachment-image" src={file.url} alt={name} />
|
||||
</Show>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<AttachmentCardV2
|
||||
title={getFilename(name)}
|
||||
hover={name}
|
||||
clickable={!!props.actions?.openAttachment}
|
||||
onClick={() => props.actions?.openAttachment?.(file)}
|
||||
>
|
||||
{typeLabel(name, file.mime)}
|
||||
</AttachmentCardV2>
|
||||
</Show>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
</Show>
|
||||
)
|
||||
|
||||
return (
|
||||
<div data-component="user-message" data-timeline-part-id={textPart()?.id}>
|
||||
<Show when={attachments().length > 0 || messageComments().length > 0}>
|
||||
<div data-slot="user-message-attachments">
|
||||
<For each={messageComments()}>
|
||||
{(comment) => (
|
||||
<CommentCardV2
|
||||
comment={comment.comment}
|
||||
path={comment.path}
|
||||
selection={comment.selection}
|
||||
title={comment.comment}
|
||||
/>
|
||||
)}
|
||||
</For>
|
||||
<For each={attachments()}>
|
||||
{(file) => {
|
||||
const type = kind(file)
|
||||
const name = file.filename ?? i18n.t("ui.message.attachment.alt")
|
||||
|
||||
return (
|
||||
<Show
|
||||
when={newLayout() && type === "file"}
|
||||
fallback={
|
||||
<div
|
||||
data-slot="user-message-attachment"
|
||||
data-type={type}
|
||||
data-clickable={type === "image" ? "true" : undefined}
|
||||
title={type === "file" ? name : undefined}
|
||||
onClick={() => {
|
||||
if (type === "image") openImagePreview(file.url, name)
|
||||
}}
|
||||
>
|
||||
<Show
|
||||
when={type === "image"}
|
||||
fallback={
|
||||
<div data-slot="user-message-attachment-file">
|
||||
<FileIcon node={{ path: name, type: "file" }} />
|
||||
<span data-slot="user-message-attachment-name">{name}</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<img data-slot="user-message-attachment-image" src={file.url} alt={name} />
|
||||
</Show>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<AttachmentCardV2
|
||||
title={getFilename(name)}
|
||||
hover={name}
|
||||
clickable={!!props.actions?.openAttachment}
|
||||
onClick={() => props.actions?.openAttachment?.(file)}
|
||||
>
|
||||
{typeLabel(name, file.mime)}
|
||||
</AttachmentCardV2>
|
||||
</Show>
|
||||
)
|
||||
}}
|
||||
</For>
|
||||
<Show when={!props.useV2Actions}>{renderAttachments()}</Show>
|
||||
<Show
|
||||
when={text()}
|
||||
fallback={
|
||||
<Show when={messageComments().length > 0}>
|
||||
<UserMessageComments comments={messageComments()} bounded={false} />
|
||||
</Show>
|
||||
}
|
||||
>
|
||||
<div data-slot="user-message-body">
|
||||
<div data-slot="user-message-text" data-comments={messageComments().length > 0 ? "true" : undefined}>
|
||||
<HighlightedText text={text()} references={inlineFiles()} agents={agents()} />
|
||||
<Show when={messageComments().length > 0}>
|
||||
<UserMessageComments comments={messageComments()} bounded />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={text()}>
|
||||
<>
|
||||
<div data-slot="user-message-body">
|
||||
<div data-slot="user-message-text">
|
||||
<HighlightedText text={text()} references={inlineFiles()} agents={agents()} />
|
||||
</div>
|
||||
</div>
|
||||
<div data-slot="user-message-copy-wrapper">
|
||||
<Show when={metaHead() || metaTail()}>
|
||||
<span data-slot="user-message-meta-wrap">
|
||||
<Show when={metaHead()}>
|
||||
<span data-slot="user-message-meta" class="text-12-regular text-text-weak cursor-default">
|
||||
{metaHead()}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={metaHead() && metaTail()}>
|
||||
<span data-slot="user-message-meta-sep" class="text-12-regular text-text-weak cursor-default">
|
||||
{"\u00A0\u00B7\u00A0"}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={metaTail()}>
|
||||
<span data-slot="user-message-meta-tail" class="text-12-regular text-text-weak cursor-default">
|
||||
{metaTail()}
|
||||
</span>
|
||||
</Show>
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={props.actions?.revert}>
|
||||
<MessageActionButton
|
||||
icon="reset"
|
||||
label={i18n.t("ui.message.revertMessage")}
|
||||
useV2={props.useV2Actions}
|
||||
disabled={!!busy()}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
revert()
|
||||
}}
|
||||
aria-label={i18n.t("ui.message.revertMessage")}
|
||||
/>
|
||||
</Show>
|
||||
<Show when={props.useV2Actions}>{renderAttachments()}</Show>
|
||||
<Show when={text() || (props.useV2Actions && messageComments().length > 0)}>
|
||||
<div data-slot="user-message-copy-wrapper">
|
||||
<Show when={metaHead() || metaTail()}>
|
||||
<span data-slot="user-message-meta-wrap">
|
||||
<Show when={metaHead()}>
|
||||
<span data-slot="user-message-meta" class="text-12-regular text-text-weak cursor-default">
|
||||
{metaHead()}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={metaHead() && metaTail()}>
|
||||
<span data-slot="user-message-meta-sep" class="text-12-regular text-text-weak cursor-default">
|
||||
{"\u00A0\u00B7\u00A0"}
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={metaTail()}>
|
||||
<span data-slot="user-message-meta-tail" class="text-12-regular text-text-weak cursor-default">
|
||||
{metaTail()}
|
||||
</span>
|
||||
</Show>
|
||||
</span>
|
||||
</Show>
|
||||
<Show when={props.actions?.revert}>
|
||||
<MessageActionButton
|
||||
icon="reset"
|
||||
label={i18n.t("ui.message.revertMessage")}
|
||||
useV2={props.useV2Actions}
|
||||
disabled={!!busy()}
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
revert()
|
||||
}}
|
||||
aria-label={i18n.t("ui.message.revertMessage")}
|
||||
/>
|
||||
</Show>
|
||||
<Show when={text()}>
|
||||
<MessageActionButton
|
||||
icon={copied() ? "check" : "copy"}
|
||||
label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copyMessage")}
|
||||
|
|
@ -1367,8 +1405,8 @@ export function UserMessageDisplay(props: {
|
|||
}}
|
||||
aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copyMessage")}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
</Show>
|
||||
</div>
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,16 @@
|
|||
box-shadow: inset 0 0 0 0.5px var(--v2-border-border-base);
|
||||
cursor: default;
|
||||
|
||||
&[data-wide] {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
&[data-surface="base"] {
|
||||
background: var(--v2-background-bg-base);
|
||||
}
|
||||
|
||||
&[data-active] {
|
||||
box-shadow: inset 0 0 0 0.5px var(--v2-border-border-strong);
|
||||
}
|
||||
|
|
@ -32,6 +42,8 @@
|
|||
}
|
||||
|
||||
[data-slot="attachment-card-v2-title"] {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,11 @@ export function AttachmentCardV2(props: {
|
|||
title: string
|
||||
active?: boolean
|
||||
clickable?: boolean
|
||||
wide?: boolean
|
||||
surface?: "base"
|
||||
/** native title attribute */
|
||||
hover?: string
|
||||
titleRef?: (element: HTMLSpanElement) => void
|
||||
onClick?: () => void
|
||||
children: JSX.Element
|
||||
}) {
|
||||
|
|
@ -16,10 +19,14 @@ export function AttachmentCardV2(props: {
|
|||
data-component="attachment-card-v2"
|
||||
data-active={props.active ? "true" : undefined}
|
||||
data-clickable={props.clickable ? "true" : undefined}
|
||||
data-wide={props.wide ? "true" : undefined}
|
||||
data-surface={props.surface}
|
||||
title={props.hover}
|
||||
onClick={() => props.onClick?.()}
|
||||
>
|
||||
<span data-slot="attachment-card-v2-title">{props.title}</span>
|
||||
<span ref={(element) => props.titleRef?.(element)} data-slot="attachment-card-v2-title">
|
||||
{props.title}
|
||||
</span>
|
||||
<span data-slot="attachment-card-v2-subtitle">{props.children}</span>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Show } from "solid-js"
|
||||
import { createSignal, onCleanup, onMount, Show } from "solid-js"
|
||||
import { FileIcon } from "@opencode-ai/ui/file-icon"
|
||||
import { getFilenameTruncated } from "@opencode-ai/core/util/path"
|
||||
import { TooltipV2 } from "@opencode-ai/ui/v2/tooltip-v2"
|
||||
import { AttachmentCardV2 } from "./attachment-card-v2"
|
||||
|
||||
export function CommentCardV2(props: {
|
||||
|
|
@ -9,19 +10,55 @@ export function CommentCardV2(props: {
|
|||
selection?: { startLine: number; endLine: number }
|
||||
active?: boolean
|
||||
title?: string
|
||||
tooltip?: boolean
|
||||
wide?: boolean
|
||||
onClick?: () => void
|
||||
}) {
|
||||
let title: HTMLSpanElement | undefined
|
||||
const [truncated, setTruncated] = createSignal(false)
|
||||
|
||||
onMount(() => {
|
||||
const element = title
|
||||
if (!element) return
|
||||
const sync = () => setTruncated(element.scrollWidth > element.clientWidth)
|
||||
const measure = () => requestAnimationFrame(sync)
|
||||
const observer = new ResizeObserver(sync)
|
||||
observer.observe(element)
|
||||
measure()
|
||||
void document.fonts?.ready.then(measure)
|
||||
onCleanup(() => observer.disconnect())
|
||||
})
|
||||
|
||||
return (
|
||||
<AttachmentCardV2 title={props.comment} active={props.active} hover={props.title} onClick={props.onClick}>
|
||||
<FileIcon node={{ path: props.path, type: "file" }} />
|
||||
<span>
|
||||
{getFilenameTruncated(props.path, 14)}
|
||||
<Show when={props.selection}>
|
||||
{(sel) =>
|
||||
sel().startLine === sel().endLine ? `:${sel().startLine}` : `:${sel().startLine}-${sel().endLine}`
|
||||
}
|
||||
</Show>
|
||||
</span>
|
||||
</AttachmentCardV2>
|
||||
<TooltipV2
|
||||
placement="top"
|
||||
openDelay={1000}
|
||||
value={props.title ?? props.comment}
|
||||
disabled={!props.tooltip || !truncated()}
|
||||
class={props.wide ? "w-full" : undefined}
|
||||
contentStyle={{ "max-width": "320px", "white-space": "pre-wrap" }}
|
||||
>
|
||||
<AttachmentCardV2
|
||||
title={props.comment}
|
||||
active={props.active}
|
||||
clickable={!!props.onClick}
|
||||
wide={props.wide}
|
||||
surface="base"
|
||||
titleRef={(element) => {
|
||||
title = element
|
||||
}}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<FileIcon node={{ path: props.path, type: "file" }} />
|
||||
<span>
|
||||
{getFilenameTruncated(props.path, 14)}
|
||||
<Show when={props.selection}>
|
||||
{(sel) =>
|
||||
sel().startLine === sel().endLine ? `:${sel().startLine}` : `:${sel().startLine}-${sel().endLine}`
|
||||
}
|
||||
</Show>
|
||||
</span>
|
||||
</AttachmentCardV2>
|
||||
</TooltipV2>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export const dict = {
|
|||
"ui.common.close": "إغلاق",
|
||||
"ui.common.next": "التالي",
|
||||
"ui.common.submit": "إرسال",
|
||||
"ui.common.showMore": "عرض المزيد",
|
||||
|
||||
"ui.permission.deny": "رفض",
|
||||
"ui.permission.allowAlways": "السماح دائمًا",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export const dict = {
|
|||
"ui.common.close": "Fechar",
|
||||
"ui.common.next": "Próximo",
|
||||
"ui.common.submit": "Enviar",
|
||||
"ui.common.showMore": "Mostrar mais",
|
||||
|
||||
"ui.permission.deny": "Negar",
|
||||
"ui.permission.allowAlways": "Permitir sempre",
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ export const dict = {
|
|||
"ui.common.close": "Zatvori",
|
||||
"ui.common.next": "Dalje",
|
||||
"ui.common.submit": "Pošalji",
|
||||
"ui.common.showMore": "Prikaži više",
|
||||
|
||||
"ui.permission.deny": "Zabrani",
|
||||
"ui.permission.allowAlways": "Uvijek dozvoli",
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ export const dict = {
|
|||
"ui.common.close": "Luk",
|
||||
"ui.common.next": "Næste",
|
||||
"ui.common.submit": "Indsend",
|
||||
"ui.common.showMore": "Vis mere",
|
||||
|
||||
"ui.permission.deny": "Afvis",
|
||||
"ui.permission.allowAlways": "Tillad altid",
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ export const dict = {
|
|||
"ui.common.close": "Schließen",
|
||||
"ui.common.next": "Weiter",
|
||||
"ui.common.submit": "Absenden",
|
||||
"ui.common.showMore": "Mehr anzeigen",
|
||||
|
||||
"ui.permission.deny": "Verweigern",
|
||||
"ui.permission.allowAlways": "Immer erlauben",
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ export const dict: Record<string, string> = {
|
|||
"ui.common.close": "Close",
|
||||
"ui.common.next": "Next",
|
||||
"ui.common.submit": "Submit",
|
||||
"ui.common.showMore": "Show more",
|
||||
|
||||
"ui.permission.deny": "Deny",
|
||||
"ui.permission.allowAlways": "Allow always",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export const dict = {
|
|||
"ui.common.close": "Cerrar",
|
||||
"ui.common.next": "Siguiente",
|
||||
"ui.common.submit": "Enviar",
|
||||
"ui.common.showMore": "Mostrar más",
|
||||
|
||||
"ui.permission.deny": "Denegar",
|
||||
"ui.permission.allowAlways": "Permitir siempre",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ export const dict = {
|
|||
"ui.common.close": "Fermer",
|
||||
"ui.common.next": "Suivant",
|
||||
"ui.common.submit": "Soumettre",
|
||||
"ui.common.showMore": "Afficher plus",
|
||||
|
||||
"ui.permission.deny": "Refuser",
|
||||
"ui.permission.allowAlways": "Toujours autoriser",
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ export const dict = {
|
|||
"ui.common.close": "閉じる",
|
||||
"ui.common.next": "次へ",
|
||||
"ui.common.submit": "送信",
|
||||
"ui.common.showMore": "さらに表示",
|
||||
|
||||
"ui.permission.deny": "拒否",
|
||||
"ui.permission.allowAlways": "常に許可",
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export const dict = {
|
|||
"ui.common.close": "닫기",
|
||||
"ui.common.next": "다음",
|
||||
"ui.common.submit": "제출",
|
||||
"ui.common.showMore": "더 보기",
|
||||
|
||||
"ui.permission.deny": "거부",
|
||||
"ui.permission.allowAlways": "항상 허용",
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ export const dict: Record<Keys, string> = {
|
|||
"ui.common.close": "Lukk",
|
||||
"ui.common.next": "Neste",
|
||||
"ui.common.submit": "Send inn",
|
||||
"ui.common.showMore": "Vis mer",
|
||||
|
||||
"ui.permission.deny": "Avslå",
|
||||
"ui.permission.allowAlways": "Tillat alltid",
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ export const dict = {
|
|||
"ui.common.close": "Zamknij",
|
||||
"ui.common.next": "Dalej",
|
||||
"ui.common.submit": "Prześlij",
|
||||
"ui.common.showMore": "Pokaż więcej",
|
||||
|
||||
"ui.permission.deny": "Odmów",
|
||||
"ui.permission.allowAlways": "Zezwalaj zawsze",
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ export const dict = {
|
|||
"ui.common.close": "Закрыть",
|
||||
"ui.common.next": "Далее",
|
||||
"ui.common.submit": "Отправить",
|
||||
"ui.common.showMore": "Показать ещё",
|
||||
|
||||
"ui.permission.deny": "Запретить",
|
||||
"ui.permission.allowAlways": "Разрешить всегда",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ export const dict = {
|
|||
"ui.common.close": "ปิด",
|
||||
"ui.common.next": "ถัดไป",
|
||||
"ui.common.submit": "ส่ง",
|
||||
"ui.common.showMore": "แสดงเพิ่มเติม",
|
||||
|
||||
"ui.permission.deny": "ปฏิเสธ",
|
||||
"ui.permission.allowAlways": "อนุญาตเสมอ",
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ export const dict = {
|
|||
"ui.common.close": "Kapat",
|
||||
"ui.common.next": "İleri",
|
||||
"ui.common.submit": "Gönder",
|
||||
"ui.common.showMore": "Daha fazla göster",
|
||||
|
||||
"ui.permission.deny": "Reddet",
|
||||
"ui.permission.allowAlways": "Her zaman izin ver",
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ export const dict: Record<string, string> = {
|
|||
"ui.common.close": "Закрити",
|
||||
"ui.common.next": "Далі",
|
||||
"ui.common.submit": "Надіслати",
|
||||
"ui.common.showMore": "Показати більше",
|
||||
|
||||
"ui.permission.deny": "Заборонити",
|
||||
"ui.permission.allowAlways": "Дозволяти завжди",
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ export const dict = {
|
|||
"ui.common.close": "关闭",
|
||||
"ui.common.next": "下一步",
|
||||
"ui.common.submit": "提交",
|
||||
"ui.common.showMore": "显示更多",
|
||||
|
||||
"ui.permission.deny": "拒绝",
|
||||
"ui.permission.allowAlways": "始终允许",
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ export const dict = {
|
|||
"ui.common.close": "關閉",
|
||||
"ui.common.next": "下一步",
|
||||
"ui.common.submit": "提交",
|
||||
"ui.common.showMore": "顯示更多",
|
||||
|
||||
"ui.permission.deny": "拒絕",
|
||||
"ui.permission.allowAlways": "永遠允許",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue