chore: workover for ssh preferences

This commit is contained in:
2026-02-26 16:16:48 +01:00
parent 6a21476894
commit 74d6035f4a
11 changed files with 130 additions and 537 deletions

View File

@@ -1,106 +0,0 @@
.credentials-panel {
display: flex;
flex-direction: column;
height: 100%;
}
.credentials-tabs {
display: flex;
gap: 4px;
padding: 8px 12px;
border-bottom: 1px solid var(--vscode-panel-border);
background-color: var(--vscode-sideBar-background);
}
.credentials-tabs button {
padding: 6px 12px;
background-color: transparent;
border: none;
border-radius: 4px;
color: var(--vscode-foreground);
font-size: 12px;
cursor: pointer;
transition: background-color 0.15s;
}
.credentials-tabs button:hover {
background-color: var(--vscode-toolbar-hoverBackground);
}
.credentials-tabs button.active {
background-color: var(--vscode-button-background);
color: var(--vscode-button-foreground);
}
.credentials-content {
flex: 1;
overflow-y: auto;
padding: 16px;
}
.credentials-form {
display: flex;
flex-direction: column;
gap: 16px;
}
.credentials-header h4 {
margin: 0 0 8px;
font-size: 16px;
font-weight: 600;
color: var(--vscode-foreground);
}
.credentials-header p {
font-size: 12px;
margin: 0;
line-height: 1.5;
}
.credentials-field {
display: flex;
flex-direction: column;
gap: 6px;
}
.credentials-field label {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 12px;
font-weight: 500;
color: var(--vscode-descriptionForeground);
}
.credentials-field input {
padding: 8px 12px;
border-radius: 4px;
font-size: 13px;
}
.toggle-visibility {
background: none;
border: none;
padding: 2px 4px;
cursor: pointer;
font-size: 14px;
opacity: 0.7;
transition: opacity 0.15s;
}
.toggle-visibility:hover {
opacity: 1;
}
.credentials-actions {
display: flex;
gap: 8px;
margin-top: 8px;
padding-top: 16px;
border-top: 1px solid var(--vscode-panel-border);
}
.credentials-actions button {
padding: 8px 16px;
font-size: 12px;
}

View File

@@ -1,207 +0,0 @@
import React, { useState, useEffect } from 'react';
import { showToast } from '../Toast';
import { useI18n } from '../../i18n';
import './CredentialsPanel.css';
interface Credentials {
ftpHost?: string;
ftpUser?: string;
ftpPassword?: string;
sshHost?: string;
sshUser?: string;
sshKeyPath?: string;
}
export const CredentialsPanel: React.FC = () => {
const { t: tr } = useI18n();
const [credentials, setCredentials] = useState<Credentials>({
ftpHost: '',
ftpUser: '',
ftpPassword: '',
sshHost: '',
sshUser: '',
sshKeyPath: '',
});
const [activeTab, setActiveTab] = useState<'ftp' | 'ssh'>('ftp');
const [showTokens, _setShowTokens] = useState(false);
// Load saved credentials (in a real app, use secure storage)
useEffect(() => {
const loadCredentials = async () => {
try {
const savedCreds = localStorage.getItem('bds-credentials');
if (savedCreds) {
setCredentials(JSON.parse(savedCreds));
}
} catch (error) {
console.error(tr('credentials.error.load'), error);
}
};
loadCredentials();
}, []);
const handleSave = async () => {
try {
// Save to localStorage (in production, use secure storage)
localStorage.setItem('bds-credentials', JSON.stringify(credentials));
showToast.success(tr('credentials.toast.saved'));
} catch (error) {
console.error(tr('credentials.error.save'), error);
showToast.error(tr('credentials.toast.saveFailed'));
}
};
const handleClear = (type: 'ftp' | 'ssh') => {
const newCreds = { ...credentials };
switch (type) {
case 'ftp':
newCreds.ftpHost = '';
newCreds.ftpUser = '';
newCreds.ftpPassword = '';
break;
case 'ssh':
newCreds.sshHost = '';
newCreds.sshUser = '';
newCreds.sshKeyPath = '';
break;
}
setCredentials(newCreds);
};
const handleTestConnection = async (type: 'ftp' | 'ssh') => {
showToast.loading(tr('credentials.toast.testing', { type: type.toUpperCase() }));
// Simulate connection test
await new Promise(resolve => setTimeout(resolve, 1500));
// In a real implementation, this would test the actual connection
showToast.dismiss();
showToast.error(tr('credentials.toast.connectionFailed'));
};
return (
<div className="credentials-panel">
<div className="credentials-tabs">
<button
className={activeTab === 'ftp' ? 'active' : ''}
onClick={() => setActiveTab('ftp')}
>
{tr('credentials.tab.ftp')}
</button>
<button
className={activeTab === 'ssh' ? 'active' : ''}
onClick={() => setActiveTab('ssh')}
>
{tr('credentials.tab.ssh')}
</button>
</div>
<div className="credentials-content">
{activeTab === 'ftp' && (
<div className="credentials-form">
<div className="credentials-header">
<h4>{tr('credentials.ftp.title')}</h4>
<p className="text-muted">
{tr('credentials.ftp.description')}
</p>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.host')}</label>
<input
type="text"
placeholder={tr('credentials.ftp.placeholder.host')}
value={credentials.ftpHost}
onChange={(e) => setCredentials({ ...credentials, ftpHost: e.target.value })}
/>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.username')}</label>
<input
type="text"
placeholder={tr('credentials.ftp.placeholder.username')}
value={credentials.ftpUser}
onChange={(e) => setCredentials({ ...credentials, ftpUser: e.target.value })}
/>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.password')}</label>
<input
type={showTokens ? 'text' : 'password'}
placeholder={tr('credentials.ftp.placeholder.password')}
value={credentials.ftpPassword}
onChange={(e) => setCredentials({ ...credentials, ftpPassword: e.target.value })}
/>
</div>
<div className="credentials-actions">
<button onClick={handleSave}>{tr('common.save')}</button>
<button className="secondary" onClick={() => handleTestConnection('ftp')}>
{tr('credentials.action.testConnection')}
</button>
<button className="secondary danger" onClick={() => handleClear('ftp')}>
{tr('common.clear')}
</button>
</div>
</div>
)}
{activeTab === 'ssh' && (
<div className="credentials-form">
<div className="credentials-header">
<h4>{tr('credentials.ssh.title')}</h4>
<p className="text-muted">
{tr('credentials.ssh.description')}
</p>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.host')}</label>
<input
type="text"
placeholder={tr('credentials.ssh.placeholder.host')}
value={credentials.sshHost}
onChange={(e) => setCredentials({ ...credentials, sshHost: e.target.value })}
/>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.username')}</label>
<input
type="text"
placeholder={tr('credentials.ssh.placeholder.username')}
value={credentials.sshUser}
onChange={(e) => setCredentials({ ...credentials, sshUser: e.target.value })}
/>
</div>
<div className="credentials-field">
<label>{tr('credentials.field.sshKeyPath')}</label>
<input
type="text"
placeholder={tr('credentials.ssh.placeholder.keyPath')}
value={credentials.sshKeyPath}
onChange={(e) => setCredentials({ ...credentials, sshKeyPath: e.target.value })}
/>
</div>
<div className="credentials-actions">
<button onClick={handleSave}>{tr('common.save')}</button>
<button className="secondary" onClick={() => handleTestConnection('ssh')}>
{tr('credentials.action.testConnection')}
</button>
<button className="secondary danger" onClick={() => handleClear('ssh')}>
{tr('common.clear')}
</button>
</div>
</div>
)}
</div>
</div>
);
};
export default CredentialsPanel;

View File

@@ -1 +0,0 @@
export { CredentialsPanel } from './CredentialsPanel';

View File

@@ -257,6 +257,22 @@
opacity: 1; opacity: 1;
} }
/* Info banner */
.setting-info-banner {
padding: 10px 16px;
margin: 0 0 4px;
background: var(--vscode-editorInfo-background, rgba(0, 120, 212, 0.1));
border-left: 3px solid var(--vscode-editorInfo-foreground, #3794ff);
border-radius: 3px;
font-size: 12px;
line-height: 1.5;
color: var(--vscode-foreground);
}
.setting-info-banner p {
margin: 0;
}
/* Action buttons */ /* Action buttons */
.setting-actions { .setting-actions {
display: flex; display: flex;

View File

@@ -23,14 +23,11 @@ export const scrollToSettingsSection = (category: SettingsCategory) => {
// Settings categories // Settings categories
interface Credentials { interface Credentials {
// FTP Publishing
ftpHost: string;
ftpUser: string;
ftpPassword: string;
// SSH Publishing // SSH Publishing
sshHost: string; sshHost: string;
sshUser: string; sshUser: string;
sshKeyPath: string; sshRemotePath: string;
sshMode: 'scp' | 'rsync';
} }
interface CategoryMetadata { interface CategoryMetadata {
@@ -48,12 +45,10 @@ const RENDER_LANGUAGE_LABEL_KEY: Record<SupportedLanguage, string> = {
}; };
const defaultCredentials: Credentials = { const defaultCredentials: Credentials = {
ftpHost: '',
ftpUser: '',
ftpPassword: '',
sshHost: '', sshHost: '',
sshUser: '', sshUser: '',
sshKeyPath: '', sshRemotePath: '',
sshMode: 'scp',
}; };
// Search icon for the search bar // Search icon for the search bar
@@ -137,7 +132,6 @@ export const SettingsView: React.FC = () => {
} = useAppStore(); } = useAppStore();
const [searchQuery, setSearchQuery] = useState(''); const [searchQuery, setSearchQuery] = useState('');
const [credentials, setCredentials] = useState<Credentials>(defaultCredentials); const [credentials, setCredentials] = useState<Credentials>(defaultCredentials);
const [showSecrets, setShowSecrets] = useState(false);
const contentRef = useRef<HTMLDivElement>(null); const contentRef = useRef<HTMLDivElement>(null);
// Project settings // Project settings
@@ -304,23 +298,11 @@ export const SettingsView: React.FC = () => {
} }
}; };
const handleClearCredentials = (type: 'ftp' | 'ssh') => { const handleClearCredentials = () => {
const newCreds = { ...credentials }; const newCreds = { ...credentials, sshHost: '', sshUser: '', sshRemotePath: '', sshMode: 'scp' as const };
switch (type) {
case 'ftp':
newCreds.ftpHost = '';
newCreds.ftpUser = '';
newCreds.ftpPassword = '';
break;
case 'ssh':
newCreds.sshHost = '';
newCreds.sshUser = '';
newCreds.sshKeyPath = '';
break;
}
setCredentials(newCreds); setCredentials(newCreds);
localStorage.setItem('bds-credentials', JSON.stringify(newCreds)); localStorage.setItem('bds-credentials', JSON.stringify(newCreds));
showToast.success(t('settings.toast.credentialsCleared', { type: type.toUpperCase() })); showToast.success(t('settings.toast.credentialsCleared', { type: 'SSH' }));
}; };
// Save project settings // Save project settings
@@ -395,7 +377,7 @@ export const SettingsView: React.FC = () => {
const contentKeywords = ['content', 'categories', 'post', 'article', 'picture', 'aside', 'page']; const contentKeywords = ['content', 'categories', 'post', 'article', 'picture', 'aside', 'page'];
const aiKeywords = ['ai', 'assistant', 'chat', 'model', 'prompt', 'system', 'api', 'key', 'claude', 'gpt', 'opencode']; const aiKeywords = ['ai', 'assistant', 'chat', 'model', 'prompt', 'system', 'api', 'key', 'claude', 'gpt', 'opencode'];
const technologyKeywords = ['technology', 'python', 'runtime', 'worker', 'webworker', 'main thread', 'execution']; const technologyKeywords = ['technology', 'python', 'runtime', 'worker', 'webworker', 'main thread', 'execution'];
const publishingKeywords = ['publishing', 'ftp', 'ssh', 'deploy', 'server', 'host', 'upload']; const publishingKeywords = ['publishing', 'ssh', 'deploy', 'server', 'host', 'upload', 'scp', 'rsync'];
const dataKeywords = ['data', 'database', 'rebuild', 'maintenance', 'posts', 'media', 'scripts', 'links', 'folder', 'filesystem']; const dataKeywords = ['data', 'database', 'rebuild', 'maintenance', 'posts', 'media', 'scripts', 'links', 'folder', 'filesystem'];
const renderProjectSettings = () => ( const renderProjectSettings = () => (
@@ -1054,123 +1036,78 @@ export const SettingsView: React.FC = () => {
); );
const renderPublishingSettings = () => ( const renderPublishingSettings = () => (
<> <SettingSection
<SettingSection id="settings-section-publishing"
id="settings-section-publishing" title={t('settings.publishing.sshTitle')}
title={t('settings.publishing.ftpTitle')} description={t('credentials.ssh.description')}
description={t('credentials.ftp.description')} hidden={!sectionHasMatches(publishingKeywords)}
hidden={!sectionHasMatches(publishingKeywords)} >
<div className="setting-info-banner">
<p>{t('settings.publishing.sshKeyAuthNotice')}</p>
</div>
<SettingRow
id="ssh-mode"
label={t('settings.publishing.sshModeLabel')}
description={t('settings.publishing.sshModeDescription')}
> >
<SettingRow <select
id="ftp-host" id="ssh-mode"
label={t('credentials.field.host')} value={credentials.sshMode}
description={t('settings.publishing.ftpHostDescription')} onChange={(e) => setCredentials({ ...credentials, sshMode: e.target.value as 'scp' | 'rsync' })}
> >
<input <option value="scp">{t('settings.publishing.sshMode.scp')}</option>
id="ftp-host" <option value="rsync">{t('settings.publishing.sshMode.rsync')}</option>
type="text" </select>
placeholder={t('credentials.ftp.placeholder.host')} </SettingRow>
value={credentials.ftpHost}
onChange={(e) => setCredentials({ ...credentials, ftpHost: e.target.value })}
/>
</SettingRow>
<SettingRow <SettingRow
id="ftp-user" id="ssh-host"
label={t('credentials.field.username')} label={t('credentials.field.host')}
description={t('settings.publishing.ftpUsernameDescription')} description={t('settings.publishing.sshHostDescription')}
>
<input
id="ftp-user"
type="text"
placeholder={t('credentials.ftp.placeholder.username')}
value={credentials.ftpUser}
onChange={(e) => setCredentials({ ...credentials, ftpUser: e.target.value })}
/>
</SettingRow>
<SettingRow
id="ftp-password"
label={t('credentials.field.password')}
description={t('settings.publishing.ftpPasswordDescription')}
>
<div className="setting-input-group">
<input
id="ftp-password"
type={showSecrets ? 'text' : 'password'}
placeholder={t('credentials.ftp.placeholder.password')}
value={credentials.ftpPassword}
onChange={(e) => setCredentials({ ...credentials, ftpPassword: e.target.value })}
/>
<button
className="setting-toggle-visibility"
onClick={() => setShowSecrets(!showSecrets)}
title={showSecrets ? t('settings.publishing.hidePassword') : t('settings.publishing.showPassword')}
>
{showSecrets ? '🔒' : '👁'}
</button>
</div>
</SettingRow>
<div className="setting-actions">
<button className="primary" onClick={handleSavePublishing}>{t('common.save')}</button>
<button className="secondary danger" onClick={() => handleClearCredentials('ftp')}>{t('common.clear')}</button>
</div>
</SettingSection>
<SettingSection
title={t('settings.publishing.sshTitle')}
description={t('credentials.ssh.description')}
hidden={!sectionHasMatches(publishingKeywords)}
> >
<SettingRow <input
id="ssh-host" id="ssh-host"
label={t('credentials.field.host')} type="text"
description={t('settings.publishing.sshHostDescription')} placeholder={t('credentials.ssh.placeholder.host')}
> value={credentials.sshHost}
<input onChange={(e) => setCredentials({ ...credentials, sshHost: e.target.value })}
id="ssh-host" />
type="text" </SettingRow>
placeholder={t('credentials.ssh.placeholder.host')}
value={credentials.sshHost}
onChange={(e) => setCredentials({ ...credentials, sshHost: e.target.value })}
/>
</SettingRow>
<SettingRow <SettingRow
id="ssh-user"
label={t('credentials.field.username')}
description={t('settings.publishing.sshUsernameDescription')}
>
<input
id="ssh-user" id="ssh-user"
label={t('credentials.field.username')} type="text"
description={t('settings.publishing.sshUsernameDescription')} placeholder={t('credentials.ssh.placeholder.username')}
> value={credentials.sshUser}
<input onChange={(e) => setCredentials({ ...credentials, sshUser: e.target.value })}
id="ssh-user" />
type="text" </SettingRow>
placeholder={t('credentials.ssh.placeholder.username')}
value={credentials.sshUser}
onChange={(e) => setCredentials({ ...credentials, sshUser: e.target.value })}
/>
</SettingRow>
<SettingRow <SettingRow
id="ssh-keypath" id="ssh-remote-path"
label={t('credentials.field.sshKeyPath')} label={t('credentials.field.sshRemotePath')}
description={t('settings.publishing.sshKeyPathDescription')} description={t('settings.publishing.sshRemotePathDescription')}
> >
<input <input
id="ssh-keypath" id="ssh-remote-path"
type="text" type="text"
placeholder={t('credentials.ssh.placeholder.keyPath')} placeholder={t('credentials.ssh.placeholder.remotePath')}
value={credentials.sshKeyPath} value={credentials.sshRemotePath}
onChange={(e) => setCredentials({ ...credentials, sshKeyPath: e.target.value })} onChange={(e) => setCredentials({ ...credentials, sshRemotePath: e.target.value })}
/> />
</SettingRow> </SettingRow>
<div className="setting-actions"> <div className="setting-actions">
<button className="primary" onClick={handleSavePublishing}>{t('common.save')}</button> <button className="primary" onClick={handleSavePublishing}>{t('common.save')}</button>
<button className="secondary danger" onClick={() => handleClearCredentials('ssh')}>{t('common.clear')}</button> <button className="secondary danger" onClick={handleClearCredentials}>{t('common.clear')}</button>
</div> </div>
</SettingSection> </SettingSection>
</>
); );
const renderDataSettings = () => ( const renderDataSettings = () => (

View File

@@ -10,7 +10,6 @@ export { MilkdownEditor } from './MilkdownEditor';
export { Lightbox, ImageGallery, useMarkdownImages } from './Lightbox'; export { Lightbox, ImageGallery, useMarkdownImages } from './Lightbox';
export { TaskPopup } from './TaskPopup'; export { TaskPopup } from './TaskPopup';
export { ResizablePanel } from './ResizablePanel'; export { ResizablePanel } from './ResizablePanel';
export { CredentialsPanel } from './CredentialsPanel';
export { SettingsView } from './SettingsView'; export { SettingsView } from './SettingsView';
export { StyleView } from './StyleView'; export { StyleView } from './StyleView';
export { TagsView, scrollToTagsSection, type TagsCategory } from './TagsView'; export { TagsView, scrollToTagsSection, type TagsCategory } from './TagsView';

View File

@@ -135,7 +135,6 @@
"settings.technology.pythonRuntimeModeDescription": "Lege fest, wo Python-Skripte für Transformationspipelines ausgeführt werden.", "settings.technology.pythonRuntimeModeDescription": "Lege fest, wo Python-Skripte für Transformationspipelines ausgeführt werden.",
"settings.technology.pythonRuntimeMode.webworker": "Web Worker (empfohlen)", "settings.technology.pythonRuntimeMode.webworker": "Web Worker (empfohlen)",
"settings.technology.pythonRuntimeMode.mainThread": "Hauptthread (Legacy)", "settings.technology.pythonRuntimeMode.mainThread": "Hauptthread (Legacy)",
"settings.publishing.ftpTitle": "FTP-Veröffentlichung",
"settings.publishing.sshTitle": "SSH-Veröffentlichung", "settings.publishing.sshTitle": "SSH-Veröffentlichung",
"settings.data.title": "Datenbankwartung", "settings.data.title": "Datenbankwartung",
"settings.data.fileSystemTitle": "Dateisystem", "settings.data.fileSystemTitle": "Dateisystem",
@@ -291,23 +290,15 @@
"credentials.toast.saveFailed": "Anmeldedaten konnten nicht gespeichert werden", "credentials.toast.saveFailed": "Anmeldedaten konnten nicht gespeichert werden",
"credentials.toast.testing": "{type}-Verbindung wird getestet...", "credentials.toast.testing": "{type}-Verbindung wird getestet...",
"credentials.toast.connectionFailed": "Verbindung fehlgeschlagen Anmeldedaten prüfen", "credentials.toast.connectionFailed": "Verbindung fehlgeschlagen Anmeldedaten prüfen",
"credentials.tab.ftp": "FTP-Zugang",
"credentials.tab.ssh": "SSH-Zugang", "credentials.tab.ssh": "SSH-Zugang",
"credentials.ftp.title": "FTP-Veröffentlichung",
"credentials.ftp.description": "Konfiguriere FTP, um deinen Blog auf einem Webserver zu veröffentlichen.",
"credentials.ssh.title": "SSH-Veröffentlichung", "credentials.ssh.title": "SSH-Veröffentlichung",
"credentials.ssh.description": "Konfiguriere SSH für eine sichere Veröffentlichung auf deinem Server.", "credentials.ssh.description": "Konfiguriere SSH für eine sichere Veröffentlichung auf deinem Server.",
"credentials.field.host": "Server", "credentials.field.host": "Server",
"credentials.field.username": "Benutzername", "credentials.field.username": "Benutzername",
"credentials.field.password": "Passwort", "credentials.field.sshRemotePath": "Remote-Pfad",
"credentials.field.sshKeyPath": "SSH-Schlüsselpfad",
"credentials.action.testConnection": "Verbindung testen",
"credentials.ftp.placeholder.host": "ftp.beispiel.de",
"credentials.ftp.placeholder.username": "ftp-benutzer",
"credentials.ftp.placeholder.password": "Passwort",
"credentials.ssh.placeholder.host": "server.beispiel.de", "credentials.ssh.placeholder.host": "server.beispiel.de",
"credentials.ssh.placeholder.username": "ssh-benutzer", "credentials.ssh.placeholder.username": "ssh-benutzer",
"credentials.ssh.placeholder.keyPath": "~/.ssh/mein_schluessel", "credentials.ssh.placeholder.remotePath": "/var/www/html",
"gitSidebar.header": "QUELLSTEUERUNG", "gitSidebar.header": "QUELLSTEUERUNG",
"gitSidebar.loading": "Laden...", "gitSidebar.loading": "Laden...",
"gitSidebar.error.fetchRemoteUpdates": "Remote-Aktualisierungen konnten nicht abgerufen werden.", "gitSidebar.error.fetchRemoteUpdates": "Remote-Aktualisierungen konnten nicht abgerufen werden.",
@@ -704,14 +695,14 @@
"settings.ai.systemPromptPlaceholder": "Systemanweisungen für den KI-Assistenten eingeben...", "settings.ai.systemPromptPlaceholder": "Systemanweisungen für den KI-Assistenten eingeben...",
"settings.ai.savePrompt": "Prompt speichern", "settings.ai.savePrompt": "Prompt speichern",
"settings.ai.resetPrompt": "Auf Standard zurücksetzen", "settings.ai.resetPrompt": "Auf Standard zurücksetzen",
"settings.publishing.ftpHostDescription": "Hostname oder IP-Adresse des FTP-Servers.",
"settings.publishing.ftpUsernameDescription": "Benutzername deines FTP-Kontos.",
"settings.publishing.ftpPasswordDescription": "Passwort deines FTP-Kontos.",
"settings.publishing.showPassword": "Passwort anzeigen",
"settings.publishing.hidePassword": "Passwort verbergen",
"settings.publishing.sshHostDescription": "Hostname oder IP-Adresse des SSH-Servers.", "settings.publishing.sshHostDescription": "Hostname oder IP-Adresse des SSH-Servers.",
"settings.publishing.sshUsernameDescription": "Benutzername deines SSH-Kontos.", "settings.publishing.sshUsernameDescription": "Benutzername deines SSH-Kontos.",
"settings.publishing.sshKeyPathDescription": "Pfad zu deiner privaten SSH-Schlüsseldatei.", "settings.publishing.sshRemotePathDescription": "Das Zielverzeichnis auf dem Remote-Server, in das dein Blog veröffentlicht wird.",
"settings.publishing.sshModeLabel": "Übertragungsmodus",
"settings.publishing.sshModeDescription": "Wähle die Dateiübertragungsmethode für die Veröffentlichung über SSH.",
"settings.publishing.sshMode.scp": "SCP",
"settings.publishing.sshMode.rsync": "rsync",
"settings.publishing.sshKeyAuthNotice": "Die SSH-Schlüsselauthentifizierung muss auf deinem System eingerichtet sein, bevor du diese Veröffentlichungsmethode nutzen kannst. Stelle sicher, dass dein öffentlicher Schlüssel in der authorized_keys-Datei des Remote-Servers hinterlegt ist.",
"settings.data.description": "Baut den lokalen Datenbankindex aus den Quelldateien neu auf. Nützlich bei extern bearbeiteten Dateien.", "settings.data.description": "Baut den lokalen Datenbankindex aus den Quelldateien neu auf. Nützlich bei extern bearbeiteten Dateien.",
"settings.data.rebuildPostsLabel": "Beitragsdatenbank neu aufbauen", "settings.data.rebuildPostsLabel": "Beitragsdatenbank neu aufbauen",
"settings.data.rebuildPostsDescription": "Alle Markdown-Beiträge neu scannen und den Datenbankindex neu aufbauen.", "settings.data.rebuildPostsDescription": "Alle Markdown-Beiträge neu scannen und den Datenbankindex neu aufbauen.",

View File

@@ -135,7 +135,6 @@
"settings.technology.pythonRuntimeModeDescription": "Choose where Python scripts execute for transform pipelines.", "settings.technology.pythonRuntimeModeDescription": "Choose where Python scripts execute for transform pipelines.",
"settings.technology.pythonRuntimeMode.webworker": "Web Worker (Recommended)", "settings.technology.pythonRuntimeMode.webworker": "Web Worker (Recommended)",
"settings.technology.pythonRuntimeMode.mainThread": "Main Thread (Legacy)", "settings.technology.pythonRuntimeMode.mainThread": "Main Thread (Legacy)",
"settings.publishing.ftpTitle": "FTP Publishing",
"settings.publishing.sshTitle": "SSH Publishing", "settings.publishing.sshTitle": "SSH Publishing",
"settings.data.title": "Database Maintenance", "settings.data.title": "Database Maintenance",
"settings.data.fileSystemTitle": "File System", "settings.data.fileSystemTitle": "File System",
@@ -291,23 +290,15 @@
"credentials.toast.saveFailed": "Failed to save credentials", "credentials.toast.saveFailed": "Failed to save credentials",
"credentials.toast.testing": "Testing {type} connection...", "credentials.toast.testing": "Testing {type} connection...",
"credentials.toast.connectionFailed": "Connection failed - check credentials", "credentials.toast.connectionFailed": "Connection failed - check credentials",
"credentials.tab.ftp": "FTP",
"credentials.tab.ssh": "SSH", "credentials.tab.ssh": "SSH",
"credentials.ftp.title": "FTP Publishing",
"credentials.ftp.description": "Configure FTP for publishing your blog to a web server.",
"credentials.ssh.title": "SSH Publishing", "credentials.ssh.title": "SSH Publishing",
"credentials.ssh.description": "Configure SSH for secure publishing to your server.", "credentials.ssh.description": "Configure SSH for secure publishing to your server.",
"credentials.field.host": "Host", "credentials.field.host": "Host",
"credentials.field.username": "Username", "credentials.field.username": "Username",
"credentials.field.password": "Password", "credentials.field.sshRemotePath": "Remote Path",
"credentials.field.sshKeyPath": "SSH Key Path",
"credentials.action.testConnection": "Test Connection",
"credentials.ftp.placeholder.host": "ftp.example.com",
"credentials.ftp.placeholder.username": "ftp-user",
"credentials.ftp.placeholder.password": "Password",
"credentials.ssh.placeholder.host": "server.example.com", "credentials.ssh.placeholder.host": "server.example.com",
"credentials.ssh.placeholder.username": "ssh-user", "credentials.ssh.placeholder.username": "ssh-user",
"credentials.ssh.placeholder.keyPath": "~/.ssh/id_rsa", "credentials.ssh.placeholder.remotePath": "/var/www/html",
"gitSidebar.header": "SOURCE CONTROL", "gitSidebar.header": "SOURCE CONTROL",
"gitSidebar.loading": "Loading...", "gitSidebar.loading": "Loading...",
"gitSidebar.error.fetchRemoteUpdates": "Failed to fetch remote updates.", "gitSidebar.error.fetchRemoteUpdates": "Failed to fetch remote updates.",
@@ -704,14 +695,14 @@
"settings.ai.systemPromptPlaceholder": "Enter system instructions for the AI assistant...", "settings.ai.systemPromptPlaceholder": "Enter system instructions for the AI assistant...",
"settings.ai.savePrompt": "Save Prompt", "settings.ai.savePrompt": "Save Prompt",
"settings.ai.resetPrompt": "Reset to Default", "settings.ai.resetPrompt": "Reset to Default",
"settings.publishing.ftpHostDescription": "The FTP server hostname or IP address.",
"settings.publishing.ftpUsernameDescription": "Your FTP account username.",
"settings.publishing.ftpPasswordDescription": "Your FTP account password.",
"settings.publishing.showPassword": "Show password",
"settings.publishing.hidePassword": "Hide password",
"settings.publishing.sshHostDescription": "The SSH server hostname or IP address.", "settings.publishing.sshHostDescription": "The SSH server hostname or IP address.",
"settings.publishing.sshUsernameDescription": "Your SSH account username.", "settings.publishing.sshUsernameDescription": "Your SSH account username.",
"settings.publishing.sshKeyPathDescription": "Path to your SSH private key file.", "settings.publishing.sshRemotePathDescription": "The destination directory on the remote server where your blog will be published.",
"settings.publishing.sshModeLabel": "Transfer Mode",
"settings.publishing.sshModeDescription": "Select the file transfer method to use when publishing via SSH.",
"settings.publishing.sshMode.scp": "SCP",
"settings.publishing.sshMode.rsync": "rsync",
"settings.publishing.sshKeyAuthNotice": "SSH key authentication must be configured on your system before using this publishing method. Ensure your public key is added to the remote server's authorized_keys file.",
"settings.data.description": "Rebuild the local database index from source files. Useful if post or media files were edited externally.", "settings.data.description": "Rebuild the local database index from source files. Useful if post or media files were edited externally.",
"settings.data.rebuildPostsLabel": "Rebuild Posts Database", "settings.data.rebuildPostsLabel": "Rebuild Posts Database",
"settings.data.rebuildPostsDescription": "Re-scan all post markdown files and rebuild the database index.", "settings.data.rebuildPostsDescription": "Re-scan all post markdown files and rebuild the database index.",

View File

@@ -135,7 +135,6 @@
"settings.technology.pythonRuntimeModeDescription": "Elige dónde se ejecutan los scripts de Python para los flujos de transformación.", "settings.technology.pythonRuntimeModeDescription": "Elige dónde se ejecutan los scripts de Python para los flujos de transformación.",
"settings.technology.pythonRuntimeMode.webworker": "Web Worker (recomendado)", "settings.technology.pythonRuntimeMode.webworker": "Web Worker (recomendado)",
"settings.technology.pythonRuntimeMode.mainThread": "Hilo principal (heredado)", "settings.technology.pythonRuntimeMode.mainThread": "Hilo principal (heredado)",
"settings.publishing.ftpTitle": "Publicación FTP",
"settings.publishing.sshTitle": "Publicación SSH", "settings.publishing.sshTitle": "Publicación SSH",
"settings.data.title": "Mantenimiento de base de datos", "settings.data.title": "Mantenimiento de base de datos",
"settings.data.fileSystemTitle": "Sistema de archivos", "settings.data.fileSystemTitle": "Sistema de archivos",
@@ -291,23 +290,15 @@
"credentials.toast.saveFailed": "No se pudieron guardar las credenciales", "credentials.toast.saveFailed": "No se pudieron guardar las credenciales",
"credentials.toast.testing": "Probando conexión {type}...", "credentials.toast.testing": "Probando conexión {type}...",
"credentials.toast.connectionFailed": "La conexión falló - revisa las credenciales", "credentials.toast.connectionFailed": "La conexión falló - revisa las credenciales",
"credentials.tab.ftp": "Acceso FTP",
"credentials.tab.ssh": "Acceso SSH", "credentials.tab.ssh": "Acceso SSH",
"credentials.ftp.title": "Publicación FTP",
"credentials.ftp.description": "Configura FTP para publicar tu blog en un servidor web.",
"credentials.ssh.title": "Publicación SSH", "credentials.ssh.title": "Publicación SSH",
"credentials.ssh.description": "Configura SSH para publicar de forma segura en tu servidor.", "credentials.ssh.description": "Configura SSH para publicar de forma segura en tu servidor.",
"credentials.field.host": "Servidor", "credentials.field.host": "Servidor",
"credentials.field.username": "Nombre de usuario", "credentials.field.username": "Nombre de usuario",
"credentials.field.password": "Contraseña", "credentials.field.sshRemotePath": "Ruta remota",
"credentials.field.sshKeyPath": "Ruta de clave SSH",
"credentials.action.testConnection": "Probar conexión",
"credentials.ftp.placeholder.host": "ftp.ejemplo.es",
"credentials.ftp.placeholder.username": "usuario-ftp",
"credentials.ftp.placeholder.password": "Contraseña",
"credentials.ssh.placeholder.host": "servidor.ejemplo.es", "credentials.ssh.placeholder.host": "servidor.ejemplo.es",
"credentials.ssh.placeholder.username": "usuario-ssh", "credentials.ssh.placeholder.username": "usuario-ssh",
"credentials.ssh.placeholder.keyPath": "~/.ssh/clave_id_rsa", "credentials.ssh.placeholder.remotePath": "/var/www/html",
"gitSidebar.header": "CONTROL DE CÓDIGO FUENTE", "gitSidebar.header": "CONTROL DE CÓDIGO FUENTE",
"gitSidebar.loading": "Cargando...", "gitSidebar.loading": "Cargando...",
"gitSidebar.error.fetchRemoteUpdates": "No se pudieron obtener las actualizaciones remotas.", "gitSidebar.error.fetchRemoteUpdates": "No se pudieron obtener las actualizaciones remotas.",
@@ -704,14 +695,14 @@
"settings.ai.systemPromptPlaceholder": "Escribe aquí tu prompt del sistema…", "settings.ai.systemPromptPlaceholder": "Escribe aquí tu prompt del sistema…",
"settings.ai.savePrompt": "Guardar prompt", "settings.ai.savePrompt": "Guardar prompt",
"settings.ai.resetPrompt": "Restablecer prompt", "settings.ai.resetPrompt": "Restablecer prompt",
"settings.publishing.ftpHostDescription": "Nombre de host o IP del servidor FTP.",
"settings.publishing.ftpUsernameDescription": "Nombre de usuario de FTP.",
"settings.publishing.ftpPasswordDescription": "Contraseña de FTP.",
"settings.publishing.showPassword": "Mostrar contraseña",
"settings.publishing.hidePassword": "Ocultar contraseña",
"settings.publishing.sshHostDescription": "Nombre de host o IP del servidor SSH.", "settings.publishing.sshHostDescription": "Nombre de host o IP del servidor SSH.",
"settings.publishing.sshUsernameDescription": "Nombre de usuario de SSH.", "settings.publishing.sshUsernameDescription": "Nombre de usuario de SSH.",
"settings.publishing.sshKeyPathDescription": "Ruta a tu clave privada SSH.", "settings.publishing.sshRemotePathDescription": "El directorio de destino en el servidor remoto donde se publicará tu blog.",
"settings.publishing.sshModeLabel": "Modo de transferencia",
"settings.publishing.sshModeDescription": "Selecciona el método de transferencia de archivos para publicar mediante SSH.",
"settings.publishing.sshMode.scp": "SCP",
"settings.publishing.sshMode.rsync": "rsync",
"settings.publishing.sshKeyAuthNotice": "La autenticación con clave SSH debe estar configurada en tu sistema antes de usar este método de publicación. Asegúrate de que tu clave pública esté agregada al archivo authorized_keys del servidor remoto.",
"settings.data.description": "Gestiona y reconstruye los datos locales.", "settings.data.description": "Gestiona y reconstruye los datos locales.",
"settings.data.rebuildPostsLabel": "Reconstruir índice de publicaciones", "settings.data.rebuildPostsLabel": "Reconstruir índice de publicaciones",
"settings.data.rebuildPostsDescription": "Escanea todas las publicaciones y actualiza el índice de datos.", "settings.data.rebuildPostsDescription": "Escanea todas las publicaciones y actualiza el índice de datos.",

View File

@@ -135,7 +135,6 @@
"settings.technology.pythonRuntimeModeDescription": "Choisissez où les scripts Python sexécutent pour les pipelines de transformation.", "settings.technology.pythonRuntimeModeDescription": "Choisissez où les scripts Python sexécutent pour les pipelines de transformation.",
"settings.technology.pythonRuntimeMode.webworker": "Web Worker (recommandé)", "settings.technology.pythonRuntimeMode.webworker": "Web Worker (recommandé)",
"settings.technology.pythonRuntimeMode.mainThread": "Thread principal (hérité)", "settings.technology.pythonRuntimeMode.mainThread": "Thread principal (hérité)",
"settings.publishing.ftpTitle": "Publication FTP",
"settings.publishing.sshTitle": "Publication SSH", "settings.publishing.sshTitle": "Publication SSH",
"settings.data.title": "Maintenance de la base de données", "settings.data.title": "Maintenance de la base de données",
"settings.data.fileSystemTitle": "Système de fichiers", "settings.data.fileSystemTitle": "Système de fichiers",
@@ -291,23 +290,15 @@
"credentials.toast.saveFailed": "Impossible denregistrer les identifiants", "credentials.toast.saveFailed": "Impossible denregistrer les identifiants",
"credentials.toast.testing": "Test de la connexion {type}...", "credentials.toast.testing": "Test de la connexion {type}...",
"credentials.toast.connectionFailed": "Échec de la connexion - vérifiez les identifiants", "credentials.toast.connectionFailed": "Échec de la connexion - vérifiez les identifiants",
"credentials.tab.ftp": "Accès FTP",
"credentials.tab.ssh": "Accès SSH", "credentials.tab.ssh": "Accès SSH",
"credentials.ftp.title": "Publication FTP",
"credentials.ftp.description": "Configurez FTP pour publier votre blog sur un serveur web.",
"credentials.ssh.title": "Publication SSH", "credentials.ssh.title": "Publication SSH",
"credentials.ssh.description": "Configurez SSH pour une publication sécurisée sur votre serveur.", "credentials.ssh.description": "Configurez SSH pour une publication sécurisée sur votre serveur.",
"credentials.field.host": "Hôte", "credentials.field.host": "Hôte",
"credentials.field.username": "Nom dutilisateur", "credentials.field.username": "Nom d'utilisateur",
"credentials.field.password": "Mot de passe", "credentials.field.sshRemotePath": "Chemin distant",
"credentials.field.sshKeyPath": "Chemin de clé SSH",
"credentials.action.testConnection": "Tester la connexion",
"credentials.ftp.placeholder.host": "ftp.exemple.fr",
"credentials.ftp.placeholder.username": "utilisateur-ftp",
"credentials.ftp.placeholder.password": "Mot de passe",
"credentials.ssh.placeholder.host": "serveur.exemple.fr", "credentials.ssh.placeholder.host": "serveur.exemple.fr",
"credentials.ssh.placeholder.username": "utilisateur-ssh", "credentials.ssh.placeholder.username": "utilisateur-ssh",
"credentials.ssh.placeholder.keyPath": "~/.ssh/ma_cle", "credentials.ssh.placeholder.remotePath": "/var/www/html",
"gitSidebar.header": "CONTRÔLE DE SOURCE", "gitSidebar.header": "CONTRÔLE DE SOURCE",
"gitSidebar.loading": "Chargement...", "gitSidebar.loading": "Chargement...",
"gitSidebar.error.fetchRemoteUpdates": "Impossible de récupérer les mises à jour distantes.", "gitSidebar.error.fetchRemoteUpdates": "Impossible de récupérer les mises à jour distantes.",
@@ -704,14 +695,14 @@
"settings.ai.systemPromptPlaceholder": "Écrivez votre prompt système ici…", "settings.ai.systemPromptPlaceholder": "Écrivez votre prompt système ici…",
"settings.ai.savePrompt": "Enregistrer le prompt", "settings.ai.savePrompt": "Enregistrer le prompt",
"settings.ai.resetPrompt": "Réinitialiser le prompt", "settings.ai.resetPrompt": "Réinitialiser le prompt",
"settings.publishing.ftpHostDescription": "Nom dhôte ou IP du serveur FTP.", "settings.publishing.sshHostDescription": "Nom d'hôte ou IP du serveur SSH.",
"settings.publishing.ftpUsernameDescription": "Nom dutilisateur FTP.", "settings.publishing.sshUsernameDescription": "Nom d'utilisateur SSH.",
"settings.publishing.ftpPasswordDescription": "Mot de passe FTP.", "settings.publishing.sshRemotePathDescription": "Le répertoire de destination sur le serveur distant où votre blog sera publié.",
"settings.publishing.showPassword": "Afficher le mot de passe", "settings.publishing.sshModeLabel": "Mode de transfert",
"settings.publishing.hidePassword": "Masquer le mot de passe", "settings.publishing.sshModeDescription": "Sélectionnez la méthode de transfert de fichiers pour la publication via SSH.",
"settings.publishing.sshHostDescription": "Nom dhôte ou IP du serveur SSH.", "settings.publishing.sshMode.scp": "SCP",
"settings.publishing.sshUsernameDescription": "Nom dutilisateur SSH.", "settings.publishing.sshMode.rsync": "rsync",
"settings.publishing.sshKeyPathDescription": "Chemin vers votre clé privée SSH.", "settings.publishing.sshKeyAuthNotice": "L'authentification par clé SSH doit être configurée sur votre système avant d'utiliser ce mode de publication. Assurez-vous que votre clé publique est ajoutée au fichier authorized_keys du serveur distant.",
"settings.data.description": "Gérez et réindexez les données locales.", "settings.data.description": "Gérez et réindexez les données locales.",
"settings.data.rebuildPostsLabel": "Reconstruire les index des articles", "settings.data.rebuildPostsLabel": "Reconstruire les index des articles",
"settings.data.rebuildPostsDescription": "Analyse tous les articles et met à jour lindex de données.", "settings.data.rebuildPostsDescription": "Analyse tous les articles et met à jour lindex de données.",

View File

@@ -135,7 +135,6 @@
"settings.technology.pythonRuntimeModeDescription": "Scegli dove eseguire gli script Python per le pipeline di trasformazione.", "settings.technology.pythonRuntimeModeDescription": "Scegli dove eseguire gli script Python per le pipeline di trasformazione.",
"settings.technology.pythonRuntimeMode.webworker": "Web Worker (consigliato)", "settings.technology.pythonRuntimeMode.webworker": "Web Worker (consigliato)",
"settings.technology.pythonRuntimeMode.mainThread": "Thread principale (legacy)", "settings.technology.pythonRuntimeMode.mainThread": "Thread principale (legacy)",
"settings.publishing.ftpTitle": "Pubblicazione FTP",
"settings.publishing.sshTitle": "Pubblicazione SSH", "settings.publishing.sshTitle": "Pubblicazione SSH",
"settings.data.title": "Manutenzione database", "settings.data.title": "Manutenzione database",
"settings.data.fileSystemTitle": "Sistema file", "settings.data.fileSystemTitle": "Sistema file",
@@ -291,23 +290,15 @@
"credentials.toast.saveFailed": "Impossibile salvare le credenziali", "credentials.toast.saveFailed": "Impossibile salvare le credenziali",
"credentials.toast.testing": "Test della connessione {type} in corso...", "credentials.toast.testing": "Test della connessione {type} in corso...",
"credentials.toast.connectionFailed": "Connessione non riuscita - controlla le credenziali", "credentials.toast.connectionFailed": "Connessione non riuscita - controlla le credenziali",
"credentials.tab.ftp": "Accesso FTP",
"credentials.tab.ssh": "Accesso SSH", "credentials.tab.ssh": "Accesso SSH",
"credentials.ftp.title": "Pubblicazione FTP",
"credentials.ftp.description": "Configura FTP per pubblicare il tuo blog su un server web.",
"credentials.ssh.title": "Pubblicazione SSH", "credentials.ssh.title": "Pubblicazione SSH",
"credentials.ssh.description": "Configura SSH per una pubblicazione sicura sul tuo server.", "credentials.ssh.description": "Configura SSH per una pubblicazione sicura sul tuo server.",
"credentials.field.host": "Server", "credentials.field.host": "Server",
"credentials.field.username": "Nome utente", "credentials.field.username": "Nome utente",
"credentials.field.password": "Password di accesso", "credentials.field.sshRemotePath": "Percorso remoto",
"credentials.field.sshKeyPath": "Percorso chiave SSH",
"credentials.action.testConnection": "Testa connessione",
"credentials.ftp.placeholder.host": "ftp.esempio.it",
"credentials.ftp.placeholder.username": "utente-ftp",
"credentials.ftp.placeholder.password": "Inserisci password",
"credentials.ssh.placeholder.host": "server.esempio.it", "credentials.ssh.placeholder.host": "server.esempio.it",
"credentials.ssh.placeholder.username": "utente-ssh", "credentials.ssh.placeholder.username": "utente-ssh",
"credentials.ssh.placeholder.keyPath": "~/.ssh/chiave_id_rsa", "credentials.ssh.placeholder.remotePath": "/var/www/html",
"gitSidebar.header": "CONTROLLO SORGENTE", "gitSidebar.header": "CONTROLLO SORGENTE",
"gitSidebar.loading": "Caricamento...", "gitSidebar.loading": "Caricamento...",
"gitSidebar.error.fetchRemoteUpdates": "Impossibile recuperare gli aggiornamenti remoti.", "gitSidebar.error.fetchRemoteUpdates": "Impossibile recuperare gli aggiornamenti remoti.",
@@ -704,14 +695,14 @@
"settings.ai.systemPromptPlaceholder": "Scrivi qui il tuo prompt di sistema…", "settings.ai.systemPromptPlaceholder": "Scrivi qui il tuo prompt di sistema…",
"settings.ai.savePrompt": "Salva prompt", "settings.ai.savePrompt": "Salva prompt",
"settings.ai.resetPrompt": "Reimposta prompt", "settings.ai.resetPrompt": "Reimposta prompt",
"settings.publishing.ftpHostDescription": "Hostname o IP del server FTP.",
"settings.publishing.ftpUsernameDescription": "Nome utente FTP.",
"settings.publishing.ftpPasswordDescription": "Password FTP.",
"settings.publishing.showPassword": "Mostra password",
"settings.publishing.hidePassword": "Nascondi password",
"settings.publishing.sshHostDescription": "Hostname o IP del server SSH.", "settings.publishing.sshHostDescription": "Hostname o IP del server SSH.",
"settings.publishing.sshUsernameDescription": "Nome utente SSH.", "settings.publishing.sshUsernameDescription": "Nome utente SSH.",
"settings.publishing.sshKeyPathDescription": "Percorso della tua chiave privata SSH.", "settings.publishing.sshRemotePathDescription": "La directory di destinazione sul server remoto in cui verrà pubblicato il tuo blog.",
"settings.publishing.sshModeLabel": "Modalità di trasferimento",
"settings.publishing.sshModeDescription": "Seleziona il metodo di trasferimento file per la pubblicazione tramite SSH.",
"settings.publishing.sshMode.scp": "SCP",
"settings.publishing.sshMode.rsync": "rsync",
"settings.publishing.sshKeyAuthNotice": "L'autenticazione con chiave SSH deve essere configurata sul tuo sistema prima di utilizzare questo metodo di pubblicazione. Assicurati che la tua chiave pubblica sia aggiunta al file authorized_keys del server remoto.",
"settings.data.description": "Gestisci e ricostruisci i dati locali.", "settings.data.description": "Gestisci e ricostruisci i dati locali.",
"settings.data.rebuildPostsLabel": "Ricostruisci indice articoli", "settings.data.rebuildPostsLabel": "Ricostruisci indice articoli",
"settings.data.rebuildPostsDescription": "Analizza tutti gli articoli e aggiorna lindice dati.", "settings.data.rebuildPostsDescription": "Analizza tutti gli articoli e aggiorna lindice dati.",