feat(ui): create, update and merge GitLab merge requests from the MR view

This commit is contained in:
2026-08-16 16:23:39 +00:00
parent 28d992ac78
commit 324dca9057
12 changed files with 575 additions and 0 deletions
@@ -14,6 +14,10 @@ import { openExternalUrl } from '@/lib/url';
import { formatDateTimeForPreference } from '@/lib/timeFormat';
import type { GitLabMergeRequestContextResult, GitLabMergeRequestSummary } from '@/lib/api/types';
import { useI18n } from '@/lib/i18n';
import { toast } from '@/components/ui';
import { Checkbox } from '@/components/ui/checkbox';
import { Input } from '@/components/ui/input';
import { Textarea } from '@/components/ui/textarea';
const mrStateColor = (state: string): string => {
switch (state) {
@@ -199,6 +203,19 @@ export const GitLabMrView: React.FC = () => {
setContextError(null);
}, [branchMr?.number]);
// A different branch MR invalidates the update/merge transient state so the
// previous MR's edit form, squash flag, and in-flight requests don't leak.
React.useEffect(() => {
setUpdateOpen(false);
setEditTitle('');
setEditDescription('');
setEditDescriptionKnown(false);
setEditDescriptionLoading(false);
setUpdating(false);
setMergeSquash(false);
setMerging(false);
}, [branchMr?.number]);
const toggleContext = React.useCallback(async (mr: GitLabMergeRequestSummary) => {
if (!currentDirectory || !gitlab?.mrContext) {
return;
@@ -226,6 +243,175 @@ export const GitLabMrView: React.FC = () => {
}
}, [contextOpen, currentDirectory, gitlab, t]);
// ---- Create / update / merge actions -----------------------------------
const [createTitle, setCreateTitle] = React.useState('');
const [createDescription, setCreateDescription] = React.useState('');
const [createTargetBranch, setCreateTargetBranch] = React.useState('main');
const [createRemoveSourceBranch, setCreateRemoveSourceBranch] = React.useState(false);
const [creating, setCreating] = React.useState(false);
const createTargetTouchedRef = React.useRef(false);
// The default target branch is the target of the repository's previously
// listed open MRs when available; otherwise fall back to main.
const defaultTargetBranch = React.useMemo(
() => openMrs.find((mr) => mr.targetBranch)?.targetBranch ?? 'main',
[openMrs],
);
// Adopt the repository's target branch default once the open-MR list
// resolves, unless the user has already typed into the field.
React.useEffect(() => {
if (branchMrLoading || branchMr || createTargetTouchedRef.current) {
return;
}
setCreateTargetBranch(defaultTargetBranch);
}, [branchMr, branchMrLoading, defaultTargetBranch]);
const [updateOpen, setUpdateOpen] = React.useState(false);
const [editTitle, setEditTitle] = React.useState('');
const [editDescription, setEditDescription] = React.useState('');
const [editDescriptionKnown, setEditDescriptionKnown] = React.useState(false);
const [editDescriptionLoading, setEditDescriptionLoading] = React.useState(false);
const [updating, setUpdating] = React.useState(false);
const [mergeSquash, setMergeSquash] = React.useState(false);
const [merging, setMerging] = React.useState(false);
const createMr = React.useCallback(async () => {
if (!currentDirectory || !currentBranch || !gitlab?.mrCreate) {
return;
}
const targetBranch = createTargetBranch.trim();
if (!targetBranch) {
return;
}
setCreating(true);
try {
const created = await gitlab.mrCreate({
directory: currentDirectory,
title: createTitle.trim() || currentBranch,
sourceBranch: currentBranch,
targetBranch,
...(createDescription.trim() ? { description: createDescription } : {}),
...(createRemoveSourceBranch ? { removeSourceBranch: true } : {}),
});
toast.success(t('contextPanel.gitlabMr.createMr.toast.created'));
// Show the created MR immediately and refresh both the branch MR and
// the open list so the card flips to the opened state.
setBranchMr(created);
setRetryToken((value) => value + 1);
// Clear the form.
setCreateTitle('');
setCreateDescription('');
setCreateRemoveSourceBranch(false);
createTargetTouchedRef.current = false;
setCreateTargetBranch(defaultTargetBranch);
} catch (error) {
toast.error(t('contextPanel.gitlabMr.createMr.toast.createFailed'), {
description: error instanceof Error ? error.message : String(error),
});
} finally {
setCreating(false);
}
}, [createDescription, createRemoveSourceBranch, createTargetBranch, createTitle, currentBranch, currentDirectory, defaultTargetBranch, gitlab, t]);
const toggleUpdate = React.useCallback(async () => {
if (!branchMr) {
return;
}
if (updateOpen) {
setUpdateOpen(false);
return;
}
setUpdateOpen(true);
setEditTitle(branchMr.title);
const knownBody = contextResult?.mr?.body;
if (typeof knownBody === 'string') {
setEditDescription(knownBody);
setEditDescriptionKnown(true);
return;
}
setEditDescription('');
setEditDescriptionKnown(false);
if (!currentDirectory || !gitlab?.mrContext) {
return;
}
setEditDescriptionLoading(true);
try {
const result = await gitlab.mrContext(currentDirectory, branchMr.number, { includeDiff: false });
if (result.connected === false) {
setEditDescription('');
return;
}
setEditDescription(result.mr?.body ?? '');
setEditDescriptionKnown(true);
} catch {
// Leave the description empty; the title can still be edited.
} finally {
setEditDescriptionLoading(false);
}
}, [branchMr, contextResult?.mr?.body, currentDirectory, gitlab, updateOpen]);
const saveMr = React.useCallback(async () => {
if (!currentDirectory || !branchMr || !gitlab?.mrUpdate) {
return;
}
const trimmedTitle = editTitle.trim();
if (!trimmedTitle) {
return;
}
setUpdating(true);
try {
await gitlab.mrUpdate({
directory: currentDirectory,
number: branchMr.number,
title: trimmedTitle,
// Only send the description when it was actually loaded so an
// unresolved description can never be wiped out by a title-only save.
...(editDescriptionKnown ? { description: editDescription } : {}),
});
toast.success(t('contextPanel.gitlabMr.updateMr.toast.updated'));
setUpdateOpen(false);
setRetryToken((value) => value + 1);
} catch (error) {
toast.error(t('contextPanel.gitlabMr.updateMr.toast.updateFailed'), {
description: error instanceof Error ? error.message : String(error),
});
} finally {
setUpdating(false);
}
}, [branchMr, currentDirectory, editDescription, editDescriptionKnown, editTitle, gitlab, t]);
const mergeMr = React.useCallback(async () => {
if (!currentDirectory || !branchMr || !gitlab?.mrMerge) {
return;
}
setMerging(true);
try {
const result = await gitlab.mrMerge({
directory: currentDirectory,
number: branchMr.number,
...(mergeSquash ? { squash: true } : {}),
});
if (result.merged) {
toast.success(t('contextPanel.gitlabMr.mergeMr.toast.merged'));
} else {
toast.error(t('contextPanel.gitlabMr.mergeMr.toast.mergeFailed'), {
...(result.message ? { description: result.message } : {}),
});
}
// Refresh the branch MR (flips to the merged state) and the open list.
setRetryToken((value) => value + 1);
} catch (error) {
toast.error(t('contextPanel.gitlabMr.mergeMr.toast.mergeFailed'), {
description: error instanceof Error ? error.message : String(error),
});
} finally {
setMerging(false);
}
}, [branchMr, currentDirectory, gitlab, mergeSquash, t]);
const formatTimestamp = React.useCallback((value?: string) => {
if (!value) {
return '';
@@ -361,8 +547,92 @@ export const GitLabMrView: React.FC = () => {
)}
{contextOpen ? t('contextPanel.gitlabMr.hideContext') : t('contextPanel.gitlabMr.loadContext')}
</Button>
{branchMr.state === 'opened' ? (
<>
<Button
variant="outline"
size="sm"
className="h-7 gap-1.5 px-2"
onClick={() => void toggleUpdate()}
disabled={updating}
>
<Icon name="edit" className="size-4" />
{t('contextPanel.gitlabMr.updateMr.toggle')}
</Button>
<div
className="flex items-center gap-2 cursor-pointer"
role="button"
tabIndex={0}
aria-pressed={mergeSquash}
onClick={() => setMergeSquash((value) => !value)}
onKeyDown={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
setMergeSquash((value) => !value);
}
}}
>
<Checkbox
size="sm"
checked={mergeSquash}
onChange={(next) => setMergeSquash(next)}
ariaLabel={t('contextPanel.gitlabMr.mergeMr.squash')}
/>
<span className="typography-ui-label text-foreground select-none">{t('contextPanel.gitlabMr.mergeMr.squash')}</span>
</div>
<Button
size="sm"
className="h-7 gap-1.5 px-2"
onClick={() => void mergeMr()}
disabled={merging || updating}
>
{merging ? <Icon name="loader-4" className="size-4 animate-spin" /> : <Icon name="git-merge" className="size-4" />}
{merging ? t('contextPanel.gitlabMr.mergeMr.merging') : t('contextPanel.gitlabMr.mergeMr.action')}
</Button>
</>
) : null}
</div>
{updateOpen && branchMr.state === 'opened' ? (
<div className="flex min-w-0 flex-col gap-2 border-t border-border/40 pt-3">
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.titleLabel')}</div>
<Input
value={editTitle}
onChange={(event) => setEditTitle(event.target.value)}
placeholder={t('contextPanel.gitlabMr.createMr.titlePlaceholder')}
/>
</label>
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.descriptionLabel')}</div>
{editDescriptionLoading ? (
<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>
) : (
<Textarea
value={editDescription}
onChange={(event) => setEditDescription(event.target.value)}
className="min-h-[80px]"
placeholder={t('gitView.pr.placeholder.whatChanged')}
/>
)}
</label>
<div className="flex justify-end">
<Button
size="sm"
className="h-7 gap-1.5 px-2"
onClick={() => void saveMr()}
disabled={updating || editDescriptionLoading || !editTitle.trim()}
>
{updating ? <Icon name="loader-4" className="size-4 animate-spin" /> : <Icon name="check" className="size-4" />}
{updating ? t('contextPanel.gitlabMr.updateMr.saving') : t('contextPanel.gitlabMr.updateMr.save')}
</Button>
</div>
</div>
) : null}
{contextOpen ? (
<div className="flex min-w-0 flex-col gap-3 border-t border-border/40 pt-3">
{contextLoading ? (
@@ -415,6 +685,80 @@ export const GitLabMrView: React.FC = () => {
</div>
) : null}
</div>
) : currentBranch ? (
<div className="flex min-w-0 flex-col gap-2 rounded-md border border-border/40 p-3">
<div className="typography-ui-label font-semibold text-foreground">{t('contextPanel.gitlabMr.createMr.title')}</div>
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.sourceBranch')}</div>
<Input value={currentBranch} readOnly />
</label>
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.targetBranch')}</div>
<Input
value={createTargetBranch}
onChange={(event) => {
createTargetTouchedRef.current = true;
setCreateTargetBranch(event.target.value);
}}
placeholder="main"
/>
</label>
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.titleLabel')}</div>
<Input
value={createTitle}
onChange={(event) => setCreateTitle(event.target.value)}
placeholder={currentBranch}
/>
</label>
<label className="space-y-1">
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.createMr.descriptionLabel')}</div>
<Textarea
value={createDescription}
onChange={(event) => setCreateDescription(event.target.value)}
className="min-h-[80px]"
placeholder={t('gitView.pr.placeholder.whatChanged')}
/>
</label>
<div
className="flex items-center gap-2 cursor-pointer"
role="button"
tabIndex={0}
aria-pressed={createRemoveSourceBranch}
onClick={() => setCreateRemoveSourceBranch((value) => !value)}
onKeyDown={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
setCreateRemoveSourceBranch((value) => !value);
}
}}
>
<Checkbox
size="sm"
checked={createRemoveSourceBranch}
onChange={(next) => setCreateRemoveSourceBranch(next)}
ariaLabel={t('contextPanel.gitlabMr.createMr.removeSourceBranch')}
/>
<span className="typography-ui-label text-foreground select-none">{t('contextPanel.gitlabMr.createMr.removeSourceBranch')}</span>
</div>
<div className="flex justify-end">
<Button
size="sm"
className="h-7 gap-1.5 px-2"
onClick={() => void createMr()}
disabled={creating || !createTargetBranch.trim()}
>
{creating ? <Icon name="loader-4" className="size-4 animate-spin" /> : <Icon name="git-pull-request" className="size-4" />}
{creating ? t('contextPanel.gitlabMr.createMr.submitting') : t('contextPanel.gitlabMr.createMr.submit')}
</Button>
</div>
</div>
) : (
<div className="typography-micro text-muted-foreground">{t('contextPanel.gitlabMr.noMrForBranch')}</div>
)}
+21
View File
@@ -3000,6 +3000,27 @@ export const dict = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab ist nicht verbunden',
'contextPanel.gitlabMr.empty.noActiveProject': 'Kein aktives Projekt',
'contextPanel.gitlabMr.actions.openSettings': 'Einstellungen öffnen',
'contextPanel.gitlabMr.createMr.title': 'Neuer Merge-Request',
'contextPanel.gitlabMr.createMr.sourceBranch': 'Quellbranch',
'contextPanel.gitlabMr.createMr.targetBranch': 'Zielbranch',
'contextPanel.gitlabMr.createMr.titleLabel': 'Titel',
'contextPanel.gitlabMr.createMr.titlePlaceholder': 'Titel des Merge-Requests',
'contextPanel.gitlabMr.createMr.descriptionLabel': 'Beschreibung',
'contextPanel.gitlabMr.createMr.removeSourceBranch': 'Quellbranch nach dem Zusammenführen löschen',
'contextPanel.gitlabMr.createMr.submit': 'Merge-Request erstellen',
'contextPanel.gitlabMr.createMr.submitting': 'Wird erstellt...',
'contextPanel.gitlabMr.createMr.toast.created': 'Merge-Request erstellt',
'contextPanel.gitlabMr.createMr.toast.createFailed': 'Merge-Request konnte nicht erstellt werden',
'contextPanel.gitlabMr.updateMr.toggle': 'Titel und Beschreibung bearbeiten',
'contextPanel.gitlabMr.updateMr.save': 'Speichern',
'contextPanel.gitlabMr.updateMr.saving': 'Wird gespeichert...',
'contextPanel.gitlabMr.updateMr.toast.updated': 'Merge-Request aktualisiert',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': 'Merge-Request konnte nicht aktualisiert werden',
'contextPanel.gitlabMr.mergeMr.action': 'Zusammenführen',
'contextPanel.gitlabMr.mergeMr.squash': 'Commits squashen',
'contextPanel.gitlabMr.mergeMr.merging': 'Wird zusammengeführt...',
'contextPanel.gitlabMr.mergeMr.toast.merged': 'Merge-Request zusammengeführt',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': 'Merge-Request konnte nicht zusammengeführt werden',
'contextRail.surface.editor.description': 'Bearbeitungskontext',
'contextRail.surface.git.description': 'Git-Kontext',
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} geänderte Datei',
+21
View File
@@ -1138,6 +1138,27 @@ export const dict = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab is not connected',
'contextPanel.gitlabMr.empty.noActiveProject': 'No active project',
'contextPanel.gitlabMr.actions.openSettings': 'Open settings',
'contextPanel.gitlabMr.createMr.title': 'New merge request',
'contextPanel.gitlabMr.createMr.sourceBranch': 'Source branch',
'contextPanel.gitlabMr.createMr.targetBranch': 'Target branch',
'contextPanel.gitlabMr.createMr.titleLabel': 'Title',
'contextPanel.gitlabMr.createMr.titlePlaceholder': 'Merge request title',
'contextPanel.gitlabMr.createMr.descriptionLabel': 'Description',
'contextPanel.gitlabMr.createMr.removeSourceBranch': 'Remove source branch on merge',
'contextPanel.gitlabMr.createMr.submit': 'Create merge request',
'contextPanel.gitlabMr.createMr.submitting': 'Creating...',
'contextPanel.gitlabMr.createMr.toast.created': 'Merge request created',
'contextPanel.gitlabMr.createMr.toast.createFailed': 'Failed to create merge request',
'contextPanel.gitlabMr.updateMr.toggle': 'Edit title & description',
'contextPanel.gitlabMr.updateMr.save': 'Save',
'contextPanel.gitlabMr.updateMr.saving': 'Saving...',
'contextPanel.gitlabMr.updateMr.toast.updated': 'Merge request updated',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': 'Failed to update merge request',
'contextPanel.gitlabMr.mergeMr.action': 'Merge',
'contextPanel.gitlabMr.mergeMr.squash': 'Squash commits',
'contextPanel.gitlabMr.mergeMr.merging': 'Merging...',
'contextPanel.gitlabMr.mergeMr.toast.merged': 'Merge request merged',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': 'Failed to merge merge request',
'contextRail.surface.editor.description': 'Edit project files',
'contextRail.surface.git.description': 'Commits, branches, and pull requests',
'contextRail.surface.git.changesCountAriaSingle': '{label}, {count} changed file',
+21
View File
@@ -1139,6 +1139,27 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.gitlabMr.error.notConnected": "GitLab no está conectado",
"contextPanel.gitlabMr.empty.noActiveProject": "Sin proyecto activo",
"contextPanel.gitlabMr.actions.openSettings": "Abrir ajustes",
"contextPanel.gitlabMr.createMr.title": "Nueva solicitud de fusión",
"contextPanel.gitlabMr.createMr.sourceBranch": "Rama de origen",
"contextPanel.gitlabMr.createMr.targetBranch": "Rama de destino",
"contextPanel.gitlabMr.createMr.titleLabel": "Título",
"contextPanel.gitlabMr.createMr.titlePlaceholder": "Título de la solicitud de fusión",
"contextPanel.gitlabMr.createMr.descriptionLabel": "Descripción",
"contextPanel.gitlabMr.createMr.removeSourceBranch": "Eliminar la rama de origen al fusionar",
"contextPanel.gitlabMr.createMr.submit": "Crear solicitud de fusión",
"contextPanel.gitlabMr.createMr.submitting": "Creando...",
"contextPanel.gitlabMr.createMr.toast.created": "Solicitud de fusión creada",
"contextPanel.gitlabMr.createMr.toast.createFailed": "No se pudo crear la solicitud de fusión",
"contextPanel.gitlabMr.updateMr.toggle": "Editar título y descripción",
"contextPanel.gitlabMr.updateMr.save": "Guardar",
"contextPanel.gitlabMr.updateMr.saving": "Guardando...",
"contextPanel.gitlabMr.updateMr.toast.updated": "Solicitud de fusión actualizada",
"contextPanel.gitlabMr.updateMr.toast.updateFailed": "No se pudo actualizar la solicitud de fusión",
"contextPanel.gitlabMr.mergeMr.action": "Fusionar",
"contextPanel.gitlabMr.mergeMr.squash": "Combinar commits",
"contextPanel.gitlabMr.mergeMr.merging": "Fusionando...",
"contextPanel.gitlabMr.mergeMr.toast.merged": "La solicitud de fusión se fusionó",
"contextPanel.gitlabMr.mergeMr.toast.mergeFailed": "No se pudo fusionar la solicitud de fusión",
"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",
+21
View File
@@ -958,6 +958,27 @@ export const dict = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab n\'est pas connecté',
'contextPanel.gitlabMr.empty.noActiveProject': 'Aucun projet actif',
'contextPanel.gitlabMr.actions.openSettings': 'Ouvrir les paramètres',
'contextPanel.gitlabMr.createMr.title': 'Nouvelle demande de fusion',
'contextPanel.gitlabMr.createMr.sourceBranch': 'Branche source',
'contextPanel.gitlabMr.createMr.targetBranch': 'Branche cible',
'contextPanel.gitlabMr.createMr.titleLabel': 'Titre',
'contextPanel.gitlabMr.createMr.titlePlaceholder': 'Titre de la demande de fusion',
'contextPanel.gitlabMr.createMr.descriptionLabel': 'Description',
'contextPanel.gitlabMr.createMr.removeSourceBranch': 'Supprimer la branche source lors de la fusion',
'contextPanel.gitlabMr.createMr.submit': 'Créer une demande de fusion',
'contextPanel.gitlabMr.createMr.submitting': 'Création...',
'contextPanel.gitlabMr.createMr.toast.created': 'Demande de fusion créée',
'contextPanel.gitlabMr.createMr.toast.createFailed': 'Échec de la création de la demande de fusion',
'contextPanel.gitlabMr.updateMr.toggle': 'Modifier le titre et la description',
'contextPanel.gitlabMr.updateMr.save': 'Enregistrer',
'contextPanel.gitlabMr.updateMr.saving': 'Enregistrement...',
'contextPanel.gitlabMr.updateMr.toast.updated': 'Demande de fusion mise à jour',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': 'Échec de la mise à jour de la demande de fusion',
'contextPanel.gitlabMr.mergeMr.action': 'Fusionner',
'contextPanel.gitlabMr.mergeMr.squash': 'Écraser les commits',
'contextPanel.gitlabMr.mergeMr.merging': 'Fusion en cours...',
'contextPanel.gitlabMr.mergeMr.toast.merged': 'La demande de fusion a été fusionnée',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': 'Échec de la fusion de la demande de fusion',
'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é',
+21
View File
@@ -1135,6 +1135,27 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab に接続されていません',
'contextPanel.gitlabMr.empty.noActiveProject': 'アクティブなプロジェクトがありません',
'contextPanel.gitlabMr.actions.openSettings': '設定を開く',
'contextPanel.gitlabMr.createMr.title': '新しいマージリクエスト',
'contextPanel.gitlabMr.createMr.sourceBranch': 'ソースブランチ',
'contextPanel.gitlabMr.createMr.targetBranch': 'ターゲットブランチ',
'contextPanel.gitlabMr.createMr.titleLabel': 'タイトル',
'contextPanel.gitlabMr.createMr.titlePlaceholder': 'マージリクエストのタイトル',
'contextPanel.gitlabMr.createMr.descriptionLabel': '説明',
'contextPanel.gitlabMr.createMr.removeSourceBranch': 'マージ時にソースブランチを削除する',
'contextPanel.gitlabMr.createMr.submit': 'マージリクエストを作成',
'contextPanel.gitlabMr.createMr.submitting': '作成中...',
'contextPanel.gitlabMr.createMr.toast.created': 'マージリクエストを作成しました',
'contextPanel.gitlabMr.createMr.toast.createFailed': 'マージリクエストの作成に失敗しました',
'contextPanel.gitlabMr.updateMr.toggle': 'タイトルと説明を編集',
'contextPanel.gitlabMr.updateMr.save': '保存',
'contextPanel.gitlabMr.updateMr.saving': '保存中...',
'contextPanel.gitlabMr.updateMr.toast.updated': 'マージリクエストを更新しました',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': 'マージリクエストの更新に失敗しました',
'contextPanel.gitlabMr.mergeMr.action': 'マージ',
'contextPanel.gitlabMr.mergeMr.squash': 'コミットをスカッシュ',
'contextPanel.gitlabMr.mergeMr.merging': 'マージ中...',
'contextPanel.gitlabMr.mergeMr.toast.merged': 'マージリクエストをマージしました',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': 'マージリクエストのマージに失敗しました',
'contextRail.surface.editor.description': 'プロジェクトのファイルを編集',
'contextRail.surface.git.description': 'コミット・ブランチ・プルリクエスト',
'contextRail.surface.git.changesCountAriaSingle': '{label}、変更ファイル{count}件',
+21
View File
@@ -1139,6 +1139,27 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab에 연결되지 않았습니다',
'contextPanel.gitlabMr.empty.noActiveProject': '활성 프로젝트가 없습니다',
'contextPanel.gitlabMr.actions.openSettings': '설정 열기',
'contextPanel.gitlabMr.createMr.title': '새 병합 요청',
'contextPanel.gitlabMr.createMr.sourceBranch': '소스 브랜치',
'contextPanel.gitlabMr.createMr.targetBranch': '대상 브랜치',
'contextPanel.gitlabMr.createMr.titleLabel': '제목',
'contextPanel.gitlabMr.createMr.titlePlaceholder': '병합 요청 제목',
'contextPanel.gitlabMr.createMr.descriptionLabel': '설명',
'contextPanel.gitlabMr.createMr.removeSourceBranch': '병합 시 소스 브랜치 삭제',
'contextPanel.gitlabMr.createMr.submit': '병합 요청 만들기',
'contextPanel.gitlabMr.createMr.submitting': '만드는 중...',
'contextPanel.gitlabMr.createMr.toast.created': '병합 요청이 생성되었습니다',
'contextPanel.gitlabMr.createMr.toast.createFailed': '병합 요청 생성에 실패했습니다',
'contextPanel.gitlabMr.updateMr.toggle': '제목 및 설명 편집',
'contextPanel.gitlabMr.updateMr.save': '저장',
'contextPanel.gitlabMr.updateMr.saving': '저장 중...',
'contextPanel.gitlabMr.updateMr.toast.updated': '병합 요청이 업데이트되었습니다',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': '병합 요청 업데이트에 실패했습니다',
'contextPanel.gitlabMr.mergeMr.action': '병합',
'contextPanel.gitlabMr.mergeMr.squash': '커밋 스쿼시',
'contextPanel.gitlabMr.mergeMr.merging': '병합 중...',
'contextPanel.gitlabMr.mergeMr.toast.merged': '병합 요청이 병합되었습니다',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': '병합 요청 병합에 실패했습니다',
'contextRail.surface.editor.description': '프로젝트 파일 편집',
'contextRail.surface.git.description': '커밋, 브랜치, 풀 리퀘스트',
'contextRail.surface.git.changesCountAriaSingle': '{label}, 변경된 파일 {count}개',
+21
View File
@@ -1475,6 +1475,27 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab nie jest połączony',
'contextPanel.gitlabMr.empty.noActiveProject': 'Brak aktywnego projektu',
'contextPanel.gitlabMr.actions.openSettings': 'Otwórz ustawienia',
'contextPanel.gitlabMr.createMr.title': 'Nowe żądanie scalenia',
'contextPanel.gitlabMr.createMr.sourceBranch': 'Gałąź źródłowa',
'contextPanel.gitlabMr.createMr.targetBranch': 'Gałąź docelowa',
'contextPanel.gitlabMr.createMr.titleLabel': 'Tytuł',
'contextPanel.gitlabMr.createMr.titlePlaceholder': 'Tytuł żądania scalenia',
'contextPanel.gitlabMr.createMr.descriptionLabel': 'Opis',
'contextPanel.gitlabMr.createMr.removeSourceBranch': 'Usuń gałąź źródłową po scaleniu',
'contextPanel.gitlabMr.createMr.submit': 'Utwórz żądanie scalenia',
'contextPanel.gitlabMr.createMr.submitting': 'Tworzenie...',
'contextPanel.gitlabMr.createMr.toast.created': 'Utworzono żądanie scalenia',
'contextPanel.gitlabMr.createMr.toast.createFailed': 'Nie udało się utworzyć żądania scalenia',
'contextPanel.gitlabMr.updateMr.toggle': 'Edytuj tytuł i opis',
'contextPanel.gitlabMr.updateMr.save': 'Zapisz',
'contextPanel.gitlabMr.updateMr.saving': 'Zapisywanie...',
'contextPanel.gitlabMr.updateMr.toast.updated': 'Zaktualizowano żądanie scalenia',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': 'Nie udało się zaktualizować żądania scalenia',
'contextPanel.gitlabMr.mergeMr.action': 'Scal',
'contextPanel.gitlabMr.mergeMr.squash': 'Składuj commity',
'contextPanel.gitlabMr.mergeMr.merging': 'Scalanie...',
'contextPanel.gitlabMr.mergeMr.toast.merged': 'Żądanie scalenia scalone',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': 'Nie udało się scalić żądania scalenia',
'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',
@@ -1139,6 +1139,27 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.gitlabMr.error.notConnected": "GitLab não está conectado",
"contextPanel.gitlabMr.empty.noActiveProject": "Nenhum projeto ativo",
"contextPanel.gitlabMr.actions.openSettings": "Abrir configurações",
"contextPanel.gitlabMr.createMr.title": "Nova solicitação de merge",
"contextPanel.gitlabMr.createMr.sourceBranch": "Branch de origem",
"contextPanel.gitlabMr.createMr.targetBranch": "Branch de destino",
"contextPanel.gitlabMr.createMr.titleLabel": "Título",
"contextPanel.gitlabMr.createMr.titlePlaceholder": "Título da solicitação de merge",
"contextPanel.gitlabMr.createMr.descriptionLabel": "Descrição",
"contextPanel.gitlabMr.createMr.removeSourceBranch": "Remover branch de origem ao mesclar",
"contextPanel.gitlabMr.createMr.submit": "Criar solicitação de merge",
"contextPanel.gitlabMr.createMr.submitting": "Criando...",
"contextPanel.gitlabMr.createMr.toast.created": "Solicitação de merge criada",
"contextPanel.gitlabMr.createMr.toast.createFailed": "Falha ao criar solicitação de merge",
"contextPanel.gitlabMr.updateMr.toggle": "Editar título e descrição",
"contextPanel.gitlabMr.updateMr.save": "Salvar",
"contextPanel.gitlabMr.updateMr.saving": "Salvando...",
"contextPanel.gitlabMr.updateMr.toast.updated": "Solicitação de merge atualizada",
"contextPanel.gitlabMr.updateMr.toast.updateFailed": "Falha ao atualizar solicitação de merge",
"contextPanel.gitlabMr.mergeMr.action": "Mesclar",
"contextPanel.gitlabMr.mergeMr.squash": "Combinar commits",
"contextPanel.gitlabMr.mergeMr.merging": "Mesclando...",
"contextPanel.gitlabMr.mergeMr.toast.merged": "Solicitação de merge mesclada",
"contextPanel.gitlabMr.mergeMr.toast.mergeFailed": "Falha ao mesclar solicitação de merge",
"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",
+21
View File
@@ -1139,6 +1139,27 @@ export const dict: Record<I18nKey, string> = {
"contextPanel.gitlabMr.error.notConnected": "GitLab не підключено",
"contextPanel.gitlabMr.empty.noActiveProject": "Немає активного проєкту",
"contextPanel.gitlabMr.actions.openSettings": "Відкрити налаштування",
"contextPanel.gitlabMr.createMr.title": "Новий запит на злиття",
"contextPanel.gitlabMr.createMr.sourceBranch": "Вихідна гілка",
"contextPanel.gitlabMr.createMr.targetBranch": "Цільова гілка",
"contextPanel.gitlabMr.createMr.titleLabel": "Назва",
"contextPanel.gitlabMr.createMr.titlePlaceholder": "Назва запиту на злиття",
"contextPanel.gitlabMr.createMr.descriptionLabel": "Опис",
"contextPanel.gitlabMr.createMr.removeSourceBranch": "Видалити вихідну гілку після злиття",
"contextPanel.gitlabMr.createMr.submit": "Створити запит на злиття",
"contextPanel.gitlabMr.createMr.submitting": "Створення...",
"contextPanel.gitlabMr.createMr.toast.created": "Запит на злиття створено",
"contextPanel.gitlabMr.createMr.toast.createFailed": "Не вдалося створити запит на злиття",
"contextPanel.gitlabMr.updateMr.toggle": "Редагувати назву та опис",
"contextPanel.gitlabMr.updateMr.save": "Зберегти",
"contextPanel.gitlabMr.updateMr.saving": "Збереження...",
"contextPanel.gitlabMr.updateMr.toast.updated": "Запит на злиття оновлено",
"contextPanel.gitlabMr.updateMr.toast.updateFailed": "Не вдалося оновити запит на злиття",
"contextPanel.gitlabMr.mergeMr.action": "Злити",
"contextPanel.gitlabMr.mergeMr.squash": "Сквошити коміти",
"contextPanel.gitlabMr.mergeMr.merging": "Злиття...",
"contextPanel.gitlabMr.mergeMr.toast.merged": "Запит на злиття злито",
"contextPanel.gitlabMr.mergeMr.toast.mergeFailed": "Не вдалося злити запит на злиття",
"contextRail.surface.editor.description": "Редагування файлів проєкту",
"contextRail.surface.git.description": "Коміти, гілки та pull request-и",
"contextRail.surface.git.changesCountAriaSingle": "{label}, {count} змінений файл",
@@ -1139,6 +1139,27 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab 未连接',
'contextPanel.gitlabMr.empty.noActiveProject': '没有活动的项目',
'contextPanel.gitlabMr.actions.openSettings': '打开设置',
'contextPanel.gitlabMr.createMr.title': '新建合并请求',
'contextPanel.gitlabMr.createMr.sourceBranch': '源分支',
'contextPanel.gitlabMr.createMr.targetBranch': '目标分支',
'contextPanel.gitlabMr.createMr.titleLabel': '标题',
'contextPanel.gitlabMr.createMr.titlePlaceholder': '合并请求标题',
'contextPanel.gitlabMr.createMr.descriptionLabel': '描述',
'contextPanel.gitlabMr.createMr.removeSourceBranch': '合并后删除源分支',
'contextPanel.gitlabMr.createMr.submit': '创建合并请求',
'contextPanel.gitlabMr.createMr.submitting': '创建中...',
'contextPanel.gitlabMr.createMr.toast.created': '合并请求已创建',
'contextPanel.gitlabMr.createMr.toast.createFailed': '创建合并请求失败',
'contextPanel.gitlabMr.updateMr.toggle': '编辑标题和描述',
'contextPanel.gitlabMr.updateMr.save': '保存',
'contextPanel.gitlabMr.updateMr.saving': '保存中...',
'contextPanel.gitlabMr.updateMr.toast.updated': '合并请求已更新',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': '更新合并请求失败',
'contextPanel.gitlabMr.mergeMr.action': '合并',
'contextPanel.gitlabMr.mergeMr.squash': '压缩提交',
'contextPanel.gitlabMr.mergeMr.merging': '合并中...',
'contextPanel.gitlabMr.mergeMr.toast.merged': '合并请求已合并',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': '合并请求合并失败',
'contextRail.surface.editor.description': '编辑项目文件',
'contextRail.surface.git.description': '提交、分支和拉取请求',
'contextRail.surface.git.changesCountAriaSingle': '{label}{count} 个更改的文件',
@@ -1151,6 +1151,27 @@ export const dict: Record<I18nKey, string> = {
'contextPanel.gitlabMr.error.notConnected': 'GitLab 未連線',
'contextPanel.gitlabMr.empty.noActiveProject': '沒有使用中的專案',
'contextPanel.gitlabMr.actions.openSettings': '開啟設定',
'contextPanel.gitlabMr.createMr.title': '新增合併請求',
'contextPanel.gitlabMr.createMr.sourceBranch': '來源分支',
'contextPanel.gitlabMr.createMr.targetBranch': '目標分支',
'contextPanel.gitlabMr.createMr.titleLabel': '標題',
'contextPanel.gitlabMr.createMr.titlePlaceholder': '合併請求標題',
'contextPanel.gitlabMr.createMr.descriptionLabel': '描述',
'contextPanel.gitlabMr.createMr.removeSourceBranch': '合併後刪除來源分支',
'contextPanel.gitlabMr.createMr.submit': '建立合併請求',
'contextPanel.gitlabMr.createMr.submitting': '建立中...',
'contextPanel.gitlabMr.createMr.toast.created': '合併請求已建立',
'contextPanel.gitlabMr.createMr.toast.createFailed': '建立合併請求失敗',
'contextPanel.gitlabMr.updateMr.toggle': '編輯標題與描述',
'contextPanel.gitlabMr.updateMr.save': '儲存',
'contextPanel.gitlabMr.updateMr.saving': '儲存中...',
'contextPanel.gitlabMr.updateMr.toast.updated': '合併請求已更新',
'contextPanel.gitlabMr.updateMr.toast.updateFailed': '更新合併請求失敗',
'contextPanel.gitlabMr.mergeMr.action': '合併',
'contextPanel.gitlabMr.mergeMr.squash': '壓縮提交',
'contextPanel.gitlabMr.mergeMr.merging': '合併中...',
'contextPanel.gitlabMr.mergeMr.toast.merged': '合併請求已合併',
'contextPanel.gitlabMr.mergeMr.toast.mergeFailed': '合併請求合併失敗',
'contextRail.surface.editor.description': '編輯專案檔案',
'contextRail.surface.git.description': '提交、分支與拉取請求',
'contextRail.surface.git.changesCountAriaSingle': '{label}{count} 個變更的檔案',