feat(ui): GitLab merge request view in the context panel
This commit is contained in:
@@ -5,6 +5,7 @@ import { DiffViewIcon } from '@/components/icons/DiffIcon';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { SortableTabsStrip } from '@/components/ui/sortable-tabs-strip';
|
||||
import { PullRequestView } from '@/components/views/PullRequestView';
|
||||
import { GitLabMrView } from '@/components/views/GitLabMrView';
|
||||
import { TerminalView } from '@/components/views/TerminalView';
|
||||
import { lazyWithChunkRecovery } from '@/lib/chunkLoadRecovery';
|
||||
|
||||
@@ -938,7 +939,7 @@ export const ContextPanel: React.FC = () => {
|
||||
: activeTab?.mode === 'git'
|
||||
? <React.Suspense fallback={null}><GitView isActive={isOpen} /></React.Suspense>
|
||||
: activeTab?.mode === 'pr'
|
||||
? (gitProvider === 'github' ? <PullRequestView /> : null)
|
||||
? (gitProvider === 'github' ? <PullRequestView /> : gitProvider === 'gitlab' ? <GitLabMrView /> : null)
|
||||
: activeTab?.mode === 'notes'
|
||||
? <ProjectContextPanel />
|
||||
: activeTab?.mode === 'plan'
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
import React from 'react';
|
||||
import { useShallow } from 'zustand/react/shallow';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ScrollShadow } from '@/components/ui/ScrollShadow';
|
||||
import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay';
|
||||
import { SimpleMarkdownRenderer } from '@/components/chat/MarkdownRenderer';
|
||||
import { useRuntimeAPIs } from '@/hooks/useRuntimeAPIs';
|
||||
import { useEffectiveDirectory } from '@/hooks/useEffectiveDirectory';
|
||||
import { useGitStatus, useGitStore } from '@/stores/useGitStore';
|
||||
import { useGitLabAuthStore } from '@/stores/useGitLabAuthStore';
|
||||
import { useUIStore } from '@/stores/useUIStore';
|
||||
import { openExternalUrl } from '@/lib/url';
|
||||
import { formatDateTimeForPreference } from '@/lib/timeFormat';
|
||||
import type { GitLabMergeRequestContextResult, GitLabMergeRequestSummary } from '@/lib/api/types';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
|
||||
const mrStateColor = (state: string): string => {
|
||||
switch (state) {
|
||||
case 'merged':
|
||||
return 'var(--pr-merged)';
|
||||
case 'closed':
|
||||
return 'var(--pr-closed)';
|
||||
default:
|
||||
return 'var(--pr-open)';
|
||||
}
|
||||
};
|
||||
|
||||
const mrAuthorLabel = (mr: GitLabMergeRequestSummary): string =>
|
||||
mr.author?.name?.trim() || mr.author?.username || '';
|
||||
|
||||
const draftBadgeClass =
|
||||
'inline-flex items-center rounded border border-border/60 bg-surface-elevated px-1.5 py-px typography-micro text-foreground';
|
||||
|
||||
/**
|
||||
* Read-only GitLab merge request surface for the context panel. Resolves the
|
||||
* same repository context GitView uses (effective directory + current branch
|
||||
* from the shared git stores) and renders the branch's merge request plus the
|
||||
* repository's open merge requests. v1 is intentionally read-only: no create,
|
||||
* update, or merge actions.
|
||||
*/
|
||||
export const GitLabMrView: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
const { git, gitlab } = useRuntimeAPIs();
|
||||
const currentDirectory = useEffectiveDirectory();
|
||||
const status = useGitStatus(currentDirectory ?? null);
|
||||
const { ensureAll } = useGitStore(useShallow((state) => ({ ensureAll: state.ensureAll })));
|
||||
|
||||
const gitlabAuthStatus = useGitLabAuthStore((state) => state.status);
|
||||
const gitlabAuthChecked = useGitLabAuthStore((state) => state.hasChecked);
|
||||
const refreshGitLabStatus = useGitLabAuthStore((state) => state.refreshStatus);
|
||||
|
||||
const setSettingsDialogOpen = useUIStore((state) => state.setSettingsDialogOpen);
|
||||
const setSettingsPage = useUIStore((state) => state.setSettingsPage);
|
||||
const timeFormatPreference = useUIStore((state) => state.timeFormatPreference);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!currentDirectory || !git) {
|
||||
return;
|
||||
}
|
||||
void ensureAll(currentDirectory, git);
|
||||
}, [currentDirectory, ensureAll, git]);
|
||||
|
||||
// Settle the connection state exactly once; the store dedupes in-flight
|
||||
// refreshes so remounts never pile up status requests.
|
||||
React.useEffect(() => {
|
||||
if (gitlabAuthChecked) {
|
||||
return;
|
||||
}
|
||||
void refreshGitLabStatus(gitlab);
|
||||
}, [gitlab, gitlabAuthChecked, refreshGitLabStatus]);
|
||||
|
||||
const currentBranch = status?.current ?? null;
|
||||
const connected = gitlabAuthChecked ? gitlabAuthStatus?.connected === true : null;
|
||||
|
||||
const openGitLabSettings = React.useCallback(() => {
|
||||
setSettingsPage('git');
|
||||
setSettingsDialogOpen(true);
|
||||
}, [setSettingsDialogOpen, setSettingsPage]);
|
||||
|
||||
// ---- Current-branch merge request --------------------------------------
|
||||
|
||||
const [branchMr, setBranchMr] = React.useState<GitLabMergeRequestSummary | null>(null);
|
||||
const [branchMrLoading, setBranchMrLoading] = React.useState(false);
|
||||
const [branchMrError, setBranchMrError] = React.useState<string | null>(null);
|
||||
const [retryToken, setRetryToken] = React.useState(0);
|
||||
|
||||
const retry = React.useCallback(() => setRetryToken((value) => value + 1), []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!currentDirectory || !currentBranch || !connected || !gitlab?.mrsList) {
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
setBranchMrLoading(true);
|
||||
setBranchMrError(null);
|
||||
void gitlab
|
||||
.mrsList(currentDirectory, { sourceBranch: currentBranch })
|
||||
.then((result) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
const candidates = result.mrs ?? [];
|
||||
// Prefer the open MR for the branch; fall back to a merged one so a
|
||||
// just-merged branch still shows its request instead of nothing.
|
||||
const matching =
|
||||
candidates.find((mr) => mr.state === 'opened')
|
||||
?? candidates.find((mr) => mr.state === 'merged')
|
||||
?? null;
|
||||
setBranchMr(matching);
|
||||
})
|
||||
.catch((error) => {
|
||||
if (!cancelled) {
|
||||
setBranchMrError(error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
setBranchMrLoading(false);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [connected, currentBranch, currentDirectory, gitlab, retryToken]);
|
||||
|
||||
// ---- Open merge requests in this repository ----------------------------
|
||||
|
||||
const [openMrs, setOpenMrs] = React.useState<GitLabMergeRequestSummary[]>([]);
|
||||
const [listPage, setListPage] = React.useState(1);
|
||||
const [listHasMore, setListHasMore] = React.useState(false);
|
||||
const [listLoading, setListLoading] = React.useState(false);
|
||||
const [listLoadingMore, setListLoadingMore] = React.useState(false);
|
||||
const [listError, setListError] = React.useState<string | null>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!currentDirectory || !connected || !gitlab?.mrsList) {
|
||||
return;
|
||||
}
|
||||
let cancelled = false;
|
||||
setListLoading(true);
|
||||
setListError(null);
|
||||
void gitlab
|
||||
.mrsList(currentDirectory, { page: 1 })
|
||||
.then((result) => {
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
setOpenMrs(result.mrs ?? []);
|
||||
setListPage(result.page ?? 1);
|
||||
setListHasMore(Boolean(result.hasMore));
|
||||
})
|
||||
.catch((error) => {
|
||||
if (!cancelled) {
|
||||
setListError(error instanceof Error ? error.message : String(error));
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
if (!cancelled) {
|
||||
setListLoading(false);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [connected, currentDirectory, gitlab, retryToken]);
|
||||
|
||||
const loadMore = React.useCallback(async () => {
|
||||
if (!currentDirectory || !connected || !gitlab?.mrsList) {
|
||||
return;
|
||||
}
|
||||
if (listLoadingMore || listLoading || !listHasMore) {
|
||||
return;
|
||||
}
|
||||
setListLoadingMore(true);
|
||||
try {
|
||||
const next = await gitlab.mrsList(currentDirectory, { page: listPage + 1 });
|
||||
setOpenMrs((previous) => [...previous, ...(next.mrs ?? [])]);
|
||||
setListPage(next.page ?? listPage + 1);
|
||||
setListHasMore(Boolean(next.hasMore));
|
||||
} catch (error) {
|
||||
setListError(error instanceof Error ? error.message : String(error));
|
||||
} finally {
|
||||
setListLoadingMore(false);
|
||||
}
|
||||
}, [connected, currentDirectory, gitlab, listHasMore, listLoading, listLoadingMore, listPage]);
|
||||
|
||||
// ---- Inline MR context (current-branch MR only) ------------------------
|
||||
|
||||
const [contextOpen, setContextOpen] = React.useState(false);
|
||||
const [contextResult, setContextResult] = React.useState<GitLabMergeRequestContextResult | null>(null);
|
||||
const [contextLoading, setContextLoading] = React.useState(false);
|
||||
const [contextError, setContextError] = React.useState<string | null>(null);
|
||||
|
||||
// A different branch MR invalidates any previously loaded context.
|
||||
React.useEffect(() => {
|
||||
setContextOpen(false);
|
||||
setContextResult(null);
|
||||
setContextError(null);
|
||||
}, [branchMr?.number]);
|
||||
|
||||
const toggleContext = React.useCallback(async (mr: GitLabMergeRequestSummary) => {
|
||||
if (!currentDirectory || !gitlab?.mrContext) {
|
||||
return;
|
||||
}
|
||||
if (contextOpen) {
|
||||
setContextOpen(false);
|
||||
setContextResult(null);
|
||||
setContextError(null);
|
||||
return;
|
||||
}
|
||||
setContextOpen(true);
|
||||
setContextLoading(true);
|
||||
setContextError(null);
|
||||
try {
|
||||
const result = await gitlab.mrContext(currentDirectory, mr.number, { includeDiff: false });
|
||||
if (result.connected === false) {
|
||||
setContextError(t('contextPanel.gitlabMr.error.notConnected'));
|
||||
} else {
|
||||
setContextResult(result);
|
||||
}
|
||||
} catch (error) {
|
||||
setContextError(error instanceof Error ? error.message : String(error));
|
||||
} finally {
|
||||
setContextLoading(false);
|
||||
}
|
||||
}, [contextOpen, currentDirectory, gitlab, t]);
|
||||
|
||||
const formatTimestamp = React.useCallback((value?: string) => {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const timestamp = Date.parse(value);
|
||||
if (!Number.isFinite(timestamp)) {
|
||||
return value;
|
||||
}
|
||||
return formatDateTimeForPreference(timestamp, timeFormatPreference, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
});
|
||||
}, [timeFormatPreference]);
|
||||
|
||||
// ---- Render ------------------------------------------------------------
|
||||
|
||||
if (!currentDirectory) {
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-3 p-6 text-center">
|
||||
<Icon name="git-merge" className="h-12 w-12 text-muted-foreground/50" />
|
||||
<div className="typography-ui-header text-foreground">{t('contextPanel.gitlabMr.title')}</div>
|
||||
<div className="max-w-sm typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.empty.noActiveProject')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (connected === null) {
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-3 p-6 text-center">
|
||||
<Icon name="loader-4" className="h-6 w-6 animate-spin text-muted-foreground" />
|
||||
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.loading')}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (connected === false) {
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center gap-3 p-6 text-center">
|
||||
<Icon name="git-merge" className="h-12 w-12 text-muted-foreground/50" />
|
||||
<div className="typography-ui-header text-foreground">{t('contextPanel.gitlabMr.error.notConnected')}</div>
|
||||
<Button variant="outline" size="sm" onClick={openGitLabSettings} className="w-fit">
|
||||
{t('contextPanel.gitlabMr.actions.openSettings')}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const branchMrStateLabel = branchMr
|
||||
? branchMr.state === 'merged'
|
||||
? t('contextPanel.gitlabMr.state.merged')
|
||||
: branchMr.state === 'closed'
|
||||
? t('contextPanel.gitlabMr.state.closed')
|
||||
: t('contextPanel.gitlabMr.state.opened')
|
||||
: '';
|
||||
const branchMrAuthor = branchMr ? mrAuthorLabel(branchMr) : '';
|
||||
const mrComments = contextResult?.comments ?? [];
|
||||
|
||||
return (
|
||||
<ScrollableOverlay
|
||||
as={ScrollShadow}
|
||||
outerClassName="h-full min-h-0"
|
||||
className="px-4 py-3"
|
||||
disableHorizontal
|
||||
preventOverscroll
|
||||
>
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<div className="typography-ui-header font-semibold text-foreground">{t('contextPanel.gitlabMr.title')}</div>
|
||||
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.listSectionTitle')}</div>
|
||||
</div>
|
||||
|
||||
{/* Current-branch merge request */}
|
||||
<section className="flex min-w-0 flex-col gap-2">
|
||||
<h3 className="typography-ui-label font-semibold text-foreground">{t('contextPanel.gitlabMr.branchSectionTitle')}</h3>
|
||||
|
||||
{branchMrLoading ? (
|
||||
<div className="flex items-center gap-2 typography-micro text-muted-foreground">
|
||||
<Icon name="loader-4" className="size-4 animate-spin" />
|
||||
{t('contextPanel.gitlabMr.loading')}
|
||||
</div>
|
||||
) : branchMrError ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="typography-ui-label text-foreground">{t('contextPanel.gitlabMr.error.loadFailed')}</div>
|
||||
<div className="typography-micro text-muted-foreground break-words">{branchMrError}</div>
|
||||
<Button variant="outline" size="sm" onClick={retry} className="w-fit">
|
||||
{t('contextPanel.preview.actions.retry')}
|
||||
</Button>
|
||||
</div>
|
||||
) : branchMr ? (
|
||||
<div className="flex min-w-0 flex-col gap-2 rounded-md border border-border/40 p-3">
|
||||
<div className="min-w-0">
|
||||
<div className="typography-ui-label text-foreground break-words leading-snug">
|
||||
<span className="text-muted-foreground">!{branchMr.number}</span> {branchMr.title}
|
||||
</div>
|
||||
<div className="mt-1 flex flex-wrap items-center gap-x-2 gap-y-1 typography-micro text-muted-foreground">
|
||||
{branchMr.draft ? (
|
||||
<span className={draftBadgeClass}>{t('contextPanel.gitlabMr.draft')}</span>
|
||||
) : null}
|
||||
<span className="inline-flex items-center gap-1" style={{ color: mrStateColor(branchMr.state) }}>
|
||||
<span className="size-1.5 rounded-full" style={{ backgroundColor: mrStateColor(branchMr.state) }} />
|
||||
{branchMrStateLabel}
|
||||
</span>
|
||||
<span className="min-w-0 truncate">{branchMr.sourceBranch} → {branchMr.targetBranch}</span>
|
||||
</div>
|
||||
{branchMrAuthor ? (
|
||||
<div className="mt-0.5 typography-micro text-muted-foreground">{branchMrAuthor}</div>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-1.5">
|
||||
<Button variant="outline" size="sm" asChild className="h-7 gap-1.5 px-2">
|
||||
<a href={branchMr.url} target="_blank" rel="noopener noreferrer">
|
||||
<Icon name="external-link" className="size-4" />
|
||||
{t('contextPanel.gitlabMr.openInGitLab')}
|
||||
</a>
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-7 gap-1.5 px-2"
|
||||
onClick={() => void toggleContext(branchMr)}
|
||||
disabled={contextLoading}
|
||||
>
|
||||
{contextLoading ? (
|
||||
<Icon name="loader-4" className="size-4 animate-spin" />
|
||||
) : contextOpen ? (
|
||||
<Icon name="arrow-down-s" className="size-4 transition-transform rotate-180" />
|
||||
) : (
|
||||
<Icon name="arrow-right-s" className="size-4" />
|
||||
)}
|
||||
{contextOpen ? t('contextPanel.gitlabMr.hideContext') : t('contextPanel.gitlabMr.loadContext')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{contextOpen ? (
|
||||
<div className="flex min-w-0 flex-col gap-3 border-t border-border/40 pt-3">
|
||||
{contextLoading ? (
|
||||
<div className="flex items-center gap-2 typography-micro text-muted-foreground">
|
||||
<Icon name="loader-4" className="size-4 animate-spin" />
|
||||
{t('contextPanel.gitlabMr.loading')}
|
||||
</div>
|
||||
) : contextError ? (
|
||||
<div className="typography-micro text-muted-foreground break-words">{contextError}</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex min-w-0 flex-col gap-1">
|
||||
<div className="typography-micro font-semibold text-foreground">{t('gitView.pr.field.description')}</div>
|
||||
{contextResult?.mr?.body?.trim() ? (
|
||||
<SimpleMarkdownRenderer
|
||||
content={contextResult.mr.body}
|
||||
className="typography-markdown-body min-w-0 text-muted-foreground break-words"
|
||||
enableFileReferences={false}
|
||||
/>
|
||||
) : (
|
||||
<div className="typography-micro text-muted-foreground">{t('gitView.pr.noDescription')}</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-col gap-2">
|
||||
<div className="typography-micro font-semibold text-foreground">{t('gitView.pr.segment.comments')}</div>
|
||||
{mrComments.length > 0 ? (
|
||||
mrComments.map((comment) => (
|
||||
<div key={comment.id} className="flex min-w-0 flex-col gap-1 rounded-lg bg-surface-elevated px-3 py-2">
|
||||
<div className="flex flex-wrap items-center gap-x-1.5 gap-y-0.5 typography-micro text-muted-foreground">
|
||||
<span className="text-foreground whitespace-nowrap">
|
||||
{comment.author?.name?.trim() || comment.author?.username || ''}
|
||||
</span>
|
||||
{comment.createdAt ? (
|
||||
<span className="whitespace-nowrap">{formatTimestamp(comment.createdAt)}</span>
|
||||
) : null}
|
||||
</div>
|
||||
<SimpleMarkdownRenderer
|
||||
content={comment.body || ''}
|
||||
className="typography-markdown-body text-foreground break-words"
|
||||
enableFileReferences={false}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="typography-micro text-muted-foreground">{t('gitView.pr.comments.empty')}</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
) : (
|
||||
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.noMrForBranch')}</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* Open merge requests in this repository */}
|
||||
<section className="flex min-w-0 flex-col gap-2">
|
||||
<h3 className="typography-ui-label font-semibold text-foreground">{t('contextPanel.gitlabMr.openMrTitle')}</h3>
|
||||
|
||||
{listLoading ? (
|
||||
<div className="flex items-center gap-2 typography-micro text-muted-foreground">
|
||||
<Icon name="loader-4" className="size-4 animate-spin" />
|
||||
{t('contextPanel.gitlabMr.loading')}
|
||||
</div>
|
||||
) : listError ? (
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="typography-ui-label text-foreground">{t('contextPanel.gitlabMr.error.loadFailed')}</div>
|
||||
<div className="typography-micro text-muted-foreground break-words">{listError}</div>
|
||||
<Button variant="outline" size="sm" onClick={retry} className="w-fit">
|
||||
{t('contextPanel.preview.actions.retry')}
|
||||
</Button>
|
||||
</div>
|
||||
) : openMrs.length === 0 ? (
|
||||
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.openMrEmpty')}</div>
|
||||
) : (
|
||||
<div className="flex min-w-0 flex-col">
|
||||
{openMrs.map((mr) => (
|
||||
<div
|
||||
key={mr.number}
|
||||
className="group flex cursor-pointer items-center gap-2 rounded py-1.5 transition-colors hover:bg-interactive-hover/30"
|
||||
onClick={() => void openExternalUrl(mr.url)}
|
||||
>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="typography-small truncate text-foreground">
|
||||
<span className="mr-1 text-muted-foreground">!{mr.number}</span>
|
||||
{mr.title}
|
||||
</p>
|
||||
<p className="typography-meta truncate text-muted-foreground">{mr.sourceBranch} → {mr.targetBranch}</p>
|
||||
</div>
|
||||
{mr.draft ? (
|
||||
<span className={draftBadgeClass}>{t('contextPanel.gitlabMr.draft')}</span>
|
||||
) : null}
|
||||
<a
|
||||
href={mr.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
aria-label={t('contextPanel.gitlabMr.openInGitLab')}
|
||||
className="hidden size-5 flex-shrink-0 items-center justify-center text-muted-foreground transition-colors hover:text-foreground group-hover:flex"
|
||||
>
|
||||
<Icon name="external-link" className="size-4" />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{listHasMore ? (
|
||||
<div className="flex justify-center py-2">
|
||||
<Button variant="ghost" size="sm" onClick={() => void loadMore()} disabled={listLoadingMore}>
|
||||
{listLoadingMore ? (
|
||||
<Icon name="loader-4" className="size-4 animate-spin" />
|
||||
) : null}
|
||||
{t('contextPanel.gitlabMr.loadMore')}
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
</div>
|
||||
</ScrollableOverlay>
|
||||
);
|
||||
};
|
||||
@@ -2980,6 +2980,25 @@ export const dict = {
|
||||
'contextRail.aria.rail': 'Kontextleiste',
|
||||
'contextPanel.editorEmpty.title': 'Kein Kontext ausgewählt',
|
||||
'contextPanel.editorEmpty.description': 'Wählen Sie etwas aus der Seitenleiste aus, um Kontext anzuzeigen.',
|
||||
'contextPanel.gitlabMr.title': 'Merge-Requests',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': 'Aktueller Zweig',
|
||||
'contextPanel.gitlabMr.openMrTitle': 'Offene Merge-Requests',
|
||||
'contextPanel.gitlabMr.listSectionTitle': 'In diesem Repository',
|
||||
'contextPanel.gitlabMr.openMrEmpty': 'Keine offenen Merge-Requests',
|
||||
'contextPanel.gitlabMr.noMrForBranch': 'Keine Merge-Request für diesen Zweig',
|
||||
'contextPanel.gitlabMr.loadContext': 'Kontext laden',
|
||||
'contextPanel.gitlabMr.hideContext': 'Kontext ausblenden',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'In GitLab öffnen',
|
||||
'contextPanel.gitlabMr.draft': 'Entwurf',
|
||||
'contextPanel.gitlabMr.state.opened': 'Offen',
|
||||
'contextPanel.gitlabMr.state.merged': 'Zusammengeführt',
|
||||
'contextPanel.gitlabMr.state.closed': 'Geschlossen',
|
||||
'contextPanel.gitlabMr.loadMore': 'Mehr laden',
|
||||
'contextPanel.gitlabMr.loading': 'Laden...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': 'Merge-Requests konnten nicht geladen werden',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab ist nicht verbunden',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': 'Kein aktives Projekt',
|
||||
'contextPanel.gitlabMr.actions.openSettings': 'Einstellungen öffnen',
|
||||
'contextRail.surface.editor.description': 'Bearbeitungskontext',
|
||||
'contextRail.surface.git.description': 'Git-Kontext',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} geänderte Datei',
|
||||
|
||||
@@ -1118,6 +1118,25 @@ export const dict = {
|
||||
'contextRail.aria.rail': 'Panel surfaces',
|
||||
'contextPanel.editorEmpty.title': 'No file open',
|
||||
'contextPanel.editorEmpty.description': 'Pick a file from the tree to start editing.',
|
||||
'contextPanel.gitlabMr.title': 'Merge requests',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': 'Current branch',
|
||||
'contextPanel.gitlabMr.openMrTitle': 'Open merge requests',
|
||||
'contextPanel.gitlabMr.listSectionTitle': 'In this repository',
|
||||
'contextPanel.gitlabMr.openMrEmpty': 'No open merge requests',
|
||||
'contextPanel.gitlabMr.noMrForBranch': 'No merge request for this branch',
|
||||
'contextPanel.gitlabMr.loadContext': 'Load context',
|
||||
'contextPanel.gitlabMr.hideContext': 'Hide context',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'Open in GitLab',
|
||||
'contextPanel.gitlabMr.draft': 'Draft',
|
||||
'contextPanel.gitlabMr.state.opened': 'Open',
|
||||
'contextPanel.gitlabMr.state.merged': 'Merged',
|
||||
'contextPanel.gitlabMr.state.closed': 'Closed',
|
||||
'contextPanel.gitlabMr.loadMore': 'Load more',
|
||||
'contextPanel.gitlabMr.loading': 'Loading...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': 'Failed to load merge requests',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab is not connected',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': 'No active project',
|
||||
'contextPanel.gitlabMr.actions.openSettings': 'Open settings',
|
||||
'contextRail.surface.editor.description': 'Edit project files',
|
||||
'contextRail.surface.git.description': 'Commits, branches, and pull requests',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} changed file',
|
||||
|
||||
@@ -1119,6 +1119,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
"contextRail.aria.rail": "Superficies del panel",
|
||||
"contextPanel.editorEmpty.title": "Ningún archivo abierto",
|
||||
"contextPanel.editorEmpty.description": "Elige un archivo del árbol para empezar a editar.",
|
||||
"contextPanel.gitlabMr.title": "Solicitudes de fusión",
|
||||
"contextPanel.gitlabMr.branchSectionTitle": "Rama actual",
|
||||
"contextPanel.gitlabMr.openMrTitle": "Solicitudes de fusión abiertas",
|
||||
"contextPanel.gitlabMr.listSectionTitle": "En este repositorio",
|
||||
"contextPanel.gitlabMr.openMrEmpty": "No hay solicitudes de fusión abiertas",
|
||||
"contextPanel.gitlabMr.noMrForBranch": "No hay solicitud de fusión para esta rama",
|
||||
"contextPanel.gitlabMr.loadContext": "Cargar contexto",
|
||||
"contextPanel.gitlabMr.hideContext": "Ocultar contexto",
|
||||
"contextPanel.gitlabMr.openInGitLab": "Abrir en GitLab",
|
||||
"contextPanel.gitlabMr.draft": "Borrador",
|
||||
"contextPanel.gitlabMr.state.opened": "Abierta",
|
||||
"contextPanel.gitlabMr.state.merged": "Fusionada",
|
||||
"contextPanel.gitlabMr.state.closed": "Cerrada",
|
||||
"contextPanel.gitlabMr.loadMore": "Cargar más",
|
||||
"contextPanel.gitlabMr.loading": "Cargando...",
|
||||
"contextPanel.gitlabMr.error.loadFailed": "No se pudieron cargar las solicitudes de fusión",
|
||||
"contextPanel.gitlabMr.error.notConnected": "GitLab no está conectado",
|
||||
"contextPanel.gitlabMr.empty.noActiveProject": "Sin proyecto activo",
|
||||
"contextPanel.gitlabMr.actions.openSettings": "Abrir ajustes",
|
||||
"contextRail.surface.editor.description": "Editar archivos del proyecto",
|
||||
"contextRail.surface.git.description": "Commits, ramas y pull requests",
|
||||
"contextRail.surface.git.changesCountAriaSingle": "{label}, {count} archivo modificado",
|
||||
|
||||
@@ -938,6 +938,25 @@ export const dict = {
|
||||
'contextRail.aria.rail': 'Surfaces du panneau',
|
||||
'contextPanel.editorEmpty.title': 'Aucun fichier ouvert',
|
||||
'contextPanel.editorEmpty.description': 'Choisissez un fichier dans l’arborescence pour commencer.',
|
||||
'contextPanel.gitlabMr.title': 'Demandes de fusion',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': 'Branche actuelle',
|
||||
'contextPanel.gitlabMr.openMrTitle': 'Demandes de fusion ouvertes',
|
||||
'contextPanel.gitlabMr.listSectionTitle': 'Dans ce dépôt',
|
||||
'contextPanel.gitlabMr.openMrEmpty': 'Aucune demande de fusion ouverte',
|
||||
'contextPanel.gitlabMr.noMrForBranch': 'Aucune demande de fusion pour cette branche',
|
||||
'contextPanel.gitlabMr.loadContext': 'Charger le contexte',
|
||||
'contextPanel.gitlabMr.hideContext': 'Masquer le contexte',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'Ouvrir dans GitLab',
|
||||
'contextPanel.gitlabMr.draft': 'Brouillon',
|
||||
'contextPanel.gitlabMr.state.opened': 'Ouverte',
|
||||
'contextPanel.gitlabMr.state.merged': 'Fusionnée',
|
||||
'contextPanel.gitlabMr.state.closed': 'Fermée',
|
||||
'contextPanel.gitlabMr.loadMore': 'Charger plus',
|
||||
'contextPanel.gitlabMr.loading': 'Chargement...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': 'Échec du chargement des demandes de fusion',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab n\'est pas connecté',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': 'Aucun projet actif',
|
||||
'contextPanel.gitlabMr.actions.openSettings': 'Ouvrir les paramètres',
|
||||
'contextRail.surface.editor.description': 'Modifier les fichiers du projet',
|
||||
'contextRail.surface.git.description': 'Commits, branches et pull requests',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} fichier modifié',
|
||||
|
||||
@@ -1115,6 +1115,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
'contextRail.aria.rail': 'パネルサーフェス',
|
||||
'contextPanel.editorEmpty.title': 'ファイルが開かれていません',
|
||||
'contextPanel.editorEmpty.description': 'ツリーからファイルを選んで編集を始めましょう。',
|
||||
'contextPanel.gitlabMr.title': 'マージリクエスト',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': '現在のブランチ',
|
||||
'contextPanel.gitlabMr.openMrTitle': '開いているマージリクエスト',
|
||||
'contextPanel.gitlabMr.listSectionTitle': 'このリポジトリ内',
|
||||
'contextPanel.gitlabMr.openMrEmpty': '開いているマージリクエストはありません',
|
||||
'contextPanel.gitlabMr.noMrForBranch': 'このブランチのマージリクエストはありません',
|
||||
'contextPanel.gitlabMr.loadContext': 'コンテキストを読み込む',
|
||||
'contextPanel.gitlabMr.hideContext': 'コンテキストを隠す',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'GitLab で開く',
|
||||
'contextPanel.gitlabMr.draft': 'ドラフト',
|
||||
'contextPanel.gitlabMr.state.opened': 'オープン',
|
||||
'contextPanel.gitlabMr.state.merged': 'マージ済み',
|
||||
'contextPanel.gitlabMr.state.closed': 'クローズ',
|
||||
'contextPanel.gitlabMr.loadMore': 'さらに読み込む',
|
||||
'contextPanel.gitlabMr.loading': '読み込み中...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': 'マージリクエストを読み込めませんでした',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab に接続されていません',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': 'アクティブなプロジェクトがありません',
|
||||
'contextPanel.gitlabMr.actions.openSettings': '設定を開く',
|
||||
'contextRail.surface.editor.description': 'プロジェクトのファイルを編集',
|
||||
'contextRail.surface.git.description': 'コミット・ブランチ・プルリクエスト',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}、変更ファイル{count}件',
|
||||
|
||||
@@ -1119,6 +1119,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
'contextRail.aria.rail': '패널 서피스',
|
||||
'contextPanel.editorEmpty.title': '열린 파일 없음',
|
||||
'contextPanel.editorEmpty.description': '트리에서 파일을 선택해 편집을 시작하세요.',
|
||||
'contextPanel.gitlabMr.title': '병합 요청',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': '현재 브랜치',
|
||||
'contextPanel.gitlabMr.openMrTitle': '열린 병합 요청',
|
||||
'contextPanel.gitlabMr.listSectionTitle': '이 저장소',
|
||||
'contextPanel.gitlabMr.openMrEmpty': '열린 병합 요청이 없습니다',
|
||||
'contextPanel.gitlabMr.noMrForBranch': '이 브랜치에 대한 병합 요청이 없습니다',
|
||||
'contextPanel.gitlabMr.loadContext': '컨텍스트 불러오기',
|
||||
'contextPanel.gitlabMr.hideContext': '컨텍스트 숨기기',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'GitLab에서 열기',
|
||||
'contextPanel.gitlabMr.draft': '초안',
|
||||
'contextPanel.gitlabMr.state.opened': '열림',
|
||||
'contextPanel.gitlabMr.state.merged': '병합됨',
|
||||
'contextPanel.gitlabMr.state.closed': '닫힘',
|
||||
'contextPanel.gitlabMr.loadMore': '더 불러오기',
|
||||
'contextPanel.gitlabMr.loading': '불러오는 중...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': '병합 요청을 불러오지 못했습니다',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab에 연결되지 않았습니다',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': '활성 프로젝트가 없습니다',
|
||||
'contextPanel.gitlabMr.actions.openSettings': '설정 열기',
|
||||
'contextRail.surface.editor.description': '프로젝트 파일 편집',
|
||||
'contextRail.surface.git.description': '커밋, 브랜치, 풀 리퀘스트',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}, 변경된 파일 {count}개',
|
||||
|
||||
@@ -1456,6 +1456,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
'contextRail.aria.rail': 'Powierzchnie panelu',
|
||||
'contextPanel.editorEmpty.title': 'Brak otwartego pliku',
|
||||
'contextPanel.editorEmpty.description': 'Wybierz plik z drzewa, aby rozpocząć edycję.',
|
||||
'contextPanel.gitlabMr.title': 'Żądania scalenia',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': 'Bieżąca gałąź',
|
||||
'contextPanel.gitlabMr.openMrTitle': 'Otwarte żądania scalenia',
|
||||
'contextPanel.gitlabMr.listSectionTitle': 'W tym repozytorium',
|
||||
'contextPanel.gitlabMr.openMrEmpty': 'Brak otwartych żądań scalenia',
|
||||
'contextPanel.gitlabMr.noMrForBranch': 'Brak żądania scalenia dla tej gałęzi',
|
||||
'contextPanel.gitlabMr.loadContext': 'Wczytaj kontekst',
|
||||
'contextPanel.gitlabMr.hideContext': 'Ukryj kontekst',
|
||||
'contextPanel.gitlabMr.openInGitLab': 'Otwórz w GitLab',
|
||||
'contextPanel.gitlabMr.draft': 'Wersja robocza',
|
||||
'contextPanel.gitlabMr.state.opened': 'Otwarte',
|
||||
'contextPanel.gitlabMr.state.merged': 'Scalone',
|
||||
'contextPanel.gitlabMr.state.closed': 'Zamknięte',
|
||||
'contextPanel.gitlabMr.loadMore': 'Wczytaj więcej',
|
||||
'contextPanel.gitlabMr.loading': 'Wczytywanie...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': 'Nie udało się wczytać żądań scalenia',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab nie jest połączony',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': 'Brak aktywnego projektu',
|
||||
'contextPanel.gitlabMr.actions.openSettings': 'Otwórz ustawienia',
|
||||
'contextRail.surface.editor.description': 'Edytuj pliki projektu',
|
||||
'contextRail.surface.git.description': 'Commity, gałęzie i pull requesty',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} zmieniony plik',
|
||||
|
||||
@@ -1119,6 +1119,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
"contextRail.aria.rail": "Superfícies do painel",
|
||||
"contextPanel.editorEmpty.title": "Nenhum arquivo aberto",
|
||||
"contextPanel.editorEmpty.description": "Escolha um arquivo na árvore para começar a editar.",
|
||||
"contextPanel.gitlabMr.title": "Solicitações de merge",
|
||||
"contextPanel.gitlabMr.branchSectionTitle": "Branch atual",
|
||||
"contextPanel.gitlabMr.openMrTitle": "Solicitações de merge abertas",
|
||||
"contextPanel.gitlabMr.listSectionTitle": "Neste repositório",
|
||||
"contextPanel.gitlabMr.openMrEmpty": "Nenhuma solicitação de merge aberta",
|
||||
"contextPanel.gitlabMr.noMrForBranch": "Nenhuma solicitação de merge para esta branch",
|
||||
"contextPanel.gitlabMr.loadContext": "Carregar contexto",
|
||||
"contextPanel.gitlabMr.hideContext": "Ocultar contexto",
|
||||
"contextPanel.gitlabMr.openInGitLab": "Abrir no GitLab",
|
||||
"contextPanel.gitlabMr.draft": "Rascunho",
|
||||
"contextPanel.gitlabMr.state.opened": "Aberta",
|
||||
"contextPanel.gitlabMr.state.merged": "Mesclada",
|
||||
"contextPanel.gitlabMr.state.closed": "Fechada",
|
||||
"contextPanel.gitlabMr.loadMore": "Carregar mais",
|
||||
"contextPanel.gitlabMr.loading": "Carregando...",
|
||||
"contextPanel.gitlabMr.error.loadFailed": "Falha ao carregar solicitações de merge",
|
||||
"contextPanel.gitlabMr.error.notConnected": "GitLab não está conectado",
|
||||
"contextPanel.gitlabMr.empty.noActiveProject": "Nenhum projeto ativo",
|
||||
"contextPanel.gitlabMr.actions.openSettings": "Abrir configurações",
|
||||
"contextRail.surface.editor.description": "Editar arquivos do projeto",
|
||||
"contextRail.surface.git.description": "Commits, branches e pull requests",
|
||||
"contextRail.surface.git.changesCountAriaSingle": "{label}, {count} arquivo modificado",
|
||||
|
||||
@@ -1119,6 +1119,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
"contextRail.aria.rail": "Поверхні панелі",
|
||||
"contextPanel.editorEmpty.title": "Файл не відкрито",
|
||||
"contextPanel.editorEmpty.description": "Виберіть файл у дереві, щоб почати редагування.",
|
||||
"contextPanel.gitlabMr.title": "Запити на злиття",
|
||||
"contextPanel.gitlabMr.branchSectionTitle": "Поточна гілка",
|
||||
"contextPanel.gitlabMr.openMrTitle": "Відкриті запити на злиття",
|
||||
"contextPanel.gitlabMr.listSectionTitle": "У цьому репозиторії",
|
||||
"contextPanel.gitlabMr.openMrEmpty": "Немає відкритих запитів на злиття",
|
||||
"contextPanel.gitlabMr.noMrForBranch": "Немає запиту на злиття для цієї гілки",
|
||||
"contextPanel.gitlabMr.loadContext": "Завантажити контекст",
|
||||
"contextPanel.gitlabMr.hideContext": "Приховати контекст",
|
||||
"contextPanel.gitlabMr.openInGitLab": "Відкрити в GitLab",
|
||||
"contextPanel.gitlabMr.draft": "Чернетка",
|
||||
"contextPanel.gitlabMr.state.opened": "Відкритий",
|
||||
"contextPanel.gitlabMr.state.merged": "Злитий",
|
||||
"contextPanel.gitlabMr.state.closed": "Закритий",
|
||||
"contextPanel.gitlabMr.loadMore": "Завантажити ще",
|
||||
"contextPanel.gitlabMr.loading": "Завантаження...",
|
||||
"contextPanel.gitlabMr.error.loadFailed": "Не вдалося завантажити запити на злиття",
|
||||
"contextPanel.gitlabMr.error.notConnected": "GitLab не підключено",
|
||||
"contextPanel.gitlabMr.empty.noActiveProject": "Немає активного проєкту",
|
||||
"contextPanel.gitlabMr.actions.openSettings": "Відкрити налаштування",
|
||||
"contextRail.surface.editor.description": "Редагування файлів проєкту",
|
||||
"contextRail.surface.git.description": "Коміти, гілки та pull request-и",
|
||||
"contextRail.surface.git.changesCountAriaSingle": "{label}, {count} змінений файл",
|
||||
|
||||
@@ -1119,6 +1119,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
'contextRail.aria.rail': '面板界面',
|
||||
'contextPanel.editorEmpty.title': '未打开文件',
|
||||
'contextPanel.editorEmpty.description': '从文件树中选择一个文件开始编辑。',
|
||||
'contextPanel.gitlabMr.title': '合并请求',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': '当前分支',
|
||||
'contextPanel.gitlabMr.openMrTitle': '打开的合并请求',
|
||||
'contextPanel.gitlabMr.listSectionTitle': '在此仓库中',
|
||||
'contextPanel.gitlabMr.openMrEmpty': '没有打开的合并请求',
|
||||
'contextPanel.gitlabMr.noMrForBranch': '此分支没有合并请求',
|
||||
'contextPanel.gitlabMr.loadContext': '加载上下文',
|
||||
'contextPanel.gitlabMr.hideContext': '隐藏上下文',
|
||||
'contextPanel.gitlabMr.openInGitLab': '在 GitLab 中打开',
|
||||
'contextPanel.gitlabMr.draft': '草稿',
|
||||
'contextPanel.gitlabMr.state.opened': '已打开',
|
||||
'contextPanel.gitlabMr.state.merged': '已合并',
|
||||
'contextPanel.gitlabMr.state.closed': '已关闭',
|
||||
'contextPanel.gitlabMr.loadMore': '加载更多',
|
||||
'contextPanel.gitlabMr.loading': '加载中...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': '加载合并请求失败',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab 未连接',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': '没有活动的项目',
|
||||
'contextPanel.gitlabMr.actions.openSettings': '打开设置',
|
||||
'contextRail.surface.editor.description': '编辑项目文件',
|
||||
'contextRail.surface.git.description': '提交、分支和拉取请求',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label},{count} 个更改的文件',
|
||||
|
||||
@@ -1131,6 +1131,25 @@ export const dict: Record<I18nKey, string> = {
|
||||
'contextRail.aria.rail': '面板介面',
|
||||
'contextPanel.editorEmpty.title': '未開啟檔案',
|
||||
'contextPanel.editorEmpty.description': '從檔案樹選擇檔案開始編輯。',
|
||||
'contextPanel.gitlabMr.title': '合併請求',
|
||||
'contextPanel.gitlabMr.branchSectionTitle': '目前分支',
|
||||
'contextPanel.gitlabMr.openMrTitle': '已開啟的合併請求',
|
||||
'contextPanel.gitlabMr.listSectionTitle': '在此存放庫中',
|
||||
'contextPanel.gitlabMr.openMrEmpty': '沒有已開啟的合併請求',
|
||||
'contextPanel.gitlabMr.noMrForBranch': '此分支沒有合併請求',
|
||||
'contextPanel.gitlabMr.loadContext': '載入內容',
|
||||
'contextPanel.gitlabMr.hideContext': '隱藏內容',
|
||||
'contextPanel.gitlabMr.openInGitLab': '在 GitLab 中開啟',
|
||||
'contextPanel.gitlabMr.draft': '草稿',
|
||||
'contextPanel.gitlabMr.state.opened': '已開啟',
|
||||
'contextPanel.gitlabMr.state.merged': '已合併',
|
||||
'contextPanel.gitlabMr.state.closed': '已關閉',
|
||||
'contextPanel.gitlabMr.loadMore': '載入更多',
|
||||
'contextPanel.gitlabMr.loading': '載入中...',
|
||||
'contextPanel.gitlabMr.error.loadFailed': '載入合併請求失敗',
|
||||
'contextPanel.gitlabMr.error.notConnected': 'GitLab 未連線',
|
||||
'contextPanel.gitlabMr.empty.noActiveProject': '沒有使用中的專案',
|
||||
'contextPanel.gitlabMr.actions.openSettings': '開啟設定',
|
||||
'contextRail.surface.editor.description': '編輯專案檔案',
|
||||
'contextRail.surface.git.description': '提交、分支與拉取請求',
|
||||
'contextRail.surface.git.changesCountAriaSingle': '{label},{count} 個變更的檔案',
|
||||
|
||||
Reference in New Issue
Block a user