diff --git a/src/components/AccessRules/AccessRulesEditor.tsx b/src/components/AccessRules/AccessRulesEditor.tsx index 94b9815..b652019 100644 --- a/src/components/AccessRules/AccessRulesEditor.tsx +++ b/src/components/AccessRules/AccessRulesEditor.tsx @@ -86,7 +86,7 @@ const RuleCard: React.FC = ({ rule, readOnly, onUpdate, onDelete @@ -140,7 +140,7 @@ const RuleCard: React.FC = ({ rule, readOnly, onUpdate, onDelete />
- {t('accessRulesEditor.delete')} + {t('delete')} onUpdate(rule.id, { delete: value })} @@ -221,13 +221,13 @@ const AddRuleForm: React.FC = ({ context, availableObjects, on
- +
@@ -246,7 +246,7 @@ const AddRuleForm: React.FC = ({ context, availableObjects, on onChange={(e) => setItem(e.target.value)} className={styles.formSelect} > - + {Object.entries(groupedObjects).map(([feature, objs]) => ( {objs.map(obj => ( @@ -281,9 +281,9 @@ const AddRuleForm: React.FC = ({ context, availableObjects, on {/* Header Row */}
-
{t('accessRulesEditor.eigeneM')}
-
{t('accessRulesEditor.gruppeG')}
-
{t('accessRulesEditor.alleA')}
+
{t('own')}
+
{t('group')}
+
{t('Alle')}
{/* CRUD Rows */} @@ -633,9 +633,9 @@ export const AccessRulesEditor: React.FC = ({ // Render tabs const tabs: { id: TabType; label: string; icon: React.ReactNode; count: number }[] = [ - { id: 'DATA', label: t('accessRulesEditor.daten'), icon: , count: groupedRules.DATA.length }, + { id: 'DATA', label: t('data'), icon: , count: groupedRules.DATA.length }, { id: 'UI', label: 'UI', icon: , count: groupedRules.UI.length }, - { id: 'RESOURCE', label: t('accessRulesEditor.ressourcen'), icon: , count: groupedRules.RESOURCE.length }, + { id: 'RESOURCE', label: t('resources'), icon: , count: groupedRules.RESOURCE.length }, { id: 'JSON', label: 'JSON', icon: , count: rules.length }, ]; @@ -644,7 +644,7 @@ export const AccessRulesEditor: React.FC = ({
- {t('accessRulesEditor.ladeBerechtigungen')} + {t('loading permissions')}
); diff --git a/src/components/AccessRules/AccessRulesTable.tsx b/src/components/AccessRules/AccessRulesTable.tsx index 38ec264..be88bc2 100644 --- a/src/components/AccessRules/AccessRulesTable.tsx +++ b/src/components/AccessRules/AccessRulesTable.tsx @@ -166,7 +166,7 @@ const AccessRuleRow: React.FC = ({ @@ -199,13 +199,13 @@ export const AccessRulesTable: React.FC = ({ - + {isDataContext && ( <> - - - + + + )} @@ -217,15 +217,15 @@ export const AccessRulesTable: React.FC = ({ - + - + - + )} diff --git a/src/components/ContentPreview/ContentPreview.tsx b/src/components/ContentPreview/ContentPreview.tsx index 1c6a225..648ca75 100644 --- a/src/components/ContentPreview/ContentPreview.tsx +++ b/src/components/ContentPreview/ContentPreview.tsx @@ -61,11 +61,11 @@ export function ContentPreview({ if (isOpen && fileId) { // Check if we have valid data if (!fileId || fileId === 'undefined' || fileId === 'null') { - setError(t('contentPreview.invalidFileId')); + setError(t('Ungültige Datei-ID')); return; } if (!fileName || fileName === 'Unknown Item') { - setError(t('contentPreview.fileNameNotAvailable')); + setError(t('Dateiname nicht verfügbar')); return; } loadPreview(); @@ -98,7 +98,7 @@ export function ContentPreview({ setError(result.error || 'Failed to load preview'); } } catch (err) { - setError(t('contentPreview.anUnexpectedErrorOccurredWhile')); + setError(t('Ein unerwarteter Fehler ist aufgetreten, während')); } }; @@ -168,7 +168,7 @@ export function ContentPreview({ previewUrl={undefined} previewContent={previewContent} fileName={fileName} - onError={() => setError(t('contentPreview.failedToLoadPdfPreview'))} + onError={() => setError(t('PDF-Vorschau konnte nicht geladen werden'))} /> ); } @@ -194,9 +194,9 @@ export function ContentPreview({ return (
- {t('contentPreview.jsonPreviewFallback')} + {t('JSON-Vorschau als Fallback')}
- {t('contentPreview.rawContent')} + {t('Rohinhalt')}
@@ -219,7 +219,7 @@ export function ContentPreview({
            setError(t('contentPreview.failedToLoadImagePreview'))}
+            onError={() => setError(t('Bildvorschau konnte nicht geladen werden'))}
           />
         );
       
@@ -230,7 +230,7 @@ export function ContentPreview({
              setError(t('contentPreview.failedToLoadHtmlPreview'))}
+              onError={() => setError(t('HTML-Vorschau konnte nicht geladen werden'))}
             />
           );
         }
@@ -240,7 +240,7 @@ export function ContentPreview({
             previewUrl={previewUrl} 
             fileName={fileName} 
             mimeType={mimeType}
-            onError={() => setError(t('contentPreview.failedToLoadTextPreview'))}
+            onError={() => setError(t('Textvorschau konnte nicht geladen werden'))}
           />
         );
       
@@ -257,7 +257,7 @@ export function ContentPreview({
               previewUrl={previewUrl} 
               previewContent={previewContent || undefined}
               fileName={fileName} 
-              onError={() => setError(t('contentPreview.failedToLoadPdfPreview'))}
+              onError={() => setError(t('PDF-Vorschau konnte nicht geladen werden'))}
             />
           );
         }
@@ -267,7 +267,7 @@ export function ContentPreview({
              setError(t('contentPreview.failedToLoadHtmlPreview'))}
+              onError={() => setError(t('HTML-Vorschau konnte nicht geladen werden'))}
             />
           );
         }
@@ -279,7 +279,7 @@ export function ContentPreview({
             previewUrl={previewUrl} 
             fileName={fileName} 
             mimeType={mimeType}
-            onError={() => setError(t('contentPreview.previewNotSupportedForThis'))}
+            onError={() => setError(t('Vorschau wird für dieses Format nicht unterstützt'))}
           />
         );
       
diff --git a/src/components/ContentPreview/UrlContentPreview.tsx b/src/components/ContentPreview/UrlContentPreview.tsx
index 29cf09b..45e1fe3 100644
--- a/src/components/ContentPreview/UrlContentPreview.tsx
+++ b/src/components/ContentPreview/UrlContentPreview.tsx
@@ -79,7 +79,7 @@ export function UrlContentPreview({
     }
     // If PDF.js also fails, show error
     setIsLoading(false);
-    setError(t('urlContentPreview.failedToLoadPdfThis'));
+    setError(t('Fehler beim Laden des PDFs'));
     setShowPdfAnyway(true);
   };
 
@@ -111,7 +111,7 @@ export function UrlContentPreview({
         } else if (isLoading && !hasLoaded && usePdfJs) {
           // PDF.js also failed, show error
           setShowPdfAnyway(true);
-          setError(t('urlContentPreview.pdfLaedtLangsamBitteVerwenden'));
+          setError(t('PDF lädt langsam, bitte verwenden'));
           setIsLoading(false);
         }
       }, QUICK_TIMEOUT);
@@ -129,7 +129,7 @@ export function UrlContentPreview({
       try {
         new URL(url);
       } catch (e) {
-        setError(t('urlContentPreview.invalidUrl'));
+        setError(t('Ungültige URL'));
         setIsLoading(false);
       }
     }
@@ -314,7 +314,7 @@ export function UrlContentPreview({
         
📄
{fileName}
-

{t('urlContentPreview.previewNotSupportedForThis')}

+

{t('Vorschau wird hierfür nicht unterstützt')}

diff --git a/src/components/ContentPreview/renderers/JsonRenderer.tsx b/src/components/ContentPreview/renderers/JsonRenderer.tsx index 13dcde2..e268756 100644 --- a/src/components/ContentPreview/renderers/JsonRenderer.tsx +++ b/src/components/ContentPreview/renderers/JsonRenderer.tsx @@ -339,7 +339,7 @@ export function JsonRenderer({ previewContent, fileName }: JsonRendererProps) { ) : ( typeof data.values[index] === 'object' && data.values[index] !== null && 'keys' in data.values[index] ? renderTable(data.values[index], level + 1, rowPath) : - {t('jsonRenderer.errorInvalidNestedData')} + {t('Fehler: Ungültige verschachtelte Daten')} ) )}
diff --git a/src/components/ContentPreview/renderers/PdfJsRenderer.tsx b/src/components/ContentPreview/renderers/PdfJsRenderer.tsx index 5d783ce..fea4d48 100644 --- a/src/components/ContentPreview/renderers/PdfJsRenderer.tsx +++ b/src/components/ContentPreview/renderers/PdfJsRenderer.tsx @@ -141,7 +141,7 @@ export function PdfJsRenderer({ return (
-

{t('pdfJsRenderer.pdfWirdGeladen')}

+

{t('PDF wird geladen')}

); } diff --git a/src/components/ContentPreview/renderers/TextRenderer.tsx b/src/components/ContentPreview/renderers/TextRenderer.tsx index 6099252..f1876a3 100644 --- a/src/components/ContentPreview/renderers/TextRenderer.tsx +++ b/src/components/ContentPreview/renderers/TextRenderer.tsx @@ -20,7 +20,7 @@ export function TextRenderer({ return (
- {t('textRenderer.textPreview')} + {t('Textvorschau')}
           
diff --git a/src/components/FlowEditor/editor/Automation2FlowEditor.tsx b/src/components/FlowEditor/editor/Automation2FlowEditor.tsx
index ea51ee0..b9a6474 100644
--- a/src/components/FlowEditor/editor/Automation2FlowEditor.tsx
+++ b/src/components/FlowEditor/editor/Automation2FlowEditor.tsx
@@ -237,7 +237,7 @@ export const Automation2FlowEditor: React.FC = ({ in
         setExecuteResult({ success: true } as ExecuteGraphResponse);
       } else {
         const label = await promptInput('Workflow-Name:', {
-          title: t('automation2FlowEditor.saveWorkflow'),
+          title: t('Workflow speichern'),
           defaultValue: 'Neuer Workflow',
           placeholder: 'Name des Workflows',
         });
@@ -595,7 +595,7 @@ export const Automation2FlowEditor: React.FC = ({ in
           
-

{t('automation2FlowEditor.ladeNodetypen')}

+

{t('Lade Nodetypen…')}

); diff --git a/src/components/FlowEditor/editor/CanvasHeader.tsx b/src/components/FlowEditor/editor/CanvasHeader.tsx index c31b9a4..9696106 100644 --- a/src/components/FlowEditor/editor/CanvasHeader.tsx +++ b/src/components/FlowEditor/editor/CanvasHeader.tsx @@ -38,9 +38,9 @@ interface CanvasHeaderProps { function _getStatusBadge(t: (key: string) => string): Record { return { - draft: { label: t('canvasHeader.entwurf'), color: 'var(--warning-color, #ffc107)' }, - published: { label: t('canvasHeader.veroeffentlicht'), color: 'var(--success-color, #28a745)' }, - archived: { label: t('canvasHeader.archiviert'), color: 'var(--text-secondary, #666)' }, + draft: { label: t('Entwurf'), color: 'var(--warning-color, #ffc107)' }, + published: { label: t('Veröffentlicht'), color: 'var(--success-color, #28a745)' }, + archived: { label: t('Archiviert'), color: 'var(--text-secondary, #666)' }, }; } @@ -153,7 +153,7 @@ export const CanvasHeader: React.FC = ({ workflows, @@ -216,9 +216,9 @@ export const CanvasHeader: React.FC = ({ workflows, className={styles.retryButton} onClick={() => setTemplateMenuOpen((p) => !p)} disabled={templateSaving} - title={t('canvasHeader.alsVorlageSpeichern')} + title={t('Als Vorlage speichern')} > - {templateSaving ? : <>{t('canvasHeader.alsVorlage')}} + {templateSaving ? : <>{t('Als Vorlage')}} {templateMenuOpen && (
@@ -244,7 +244,7 @@ export const CanvasHeader: React.FC = ({ workflows, }} style={{ padding: '0.4rem', minWidth: 180 }} > - + {workflows.map((w) => (
diff --git a/src/components/FlowEditor/editor/FlowCanvas.tsx b/src/components/FlowEditor/editor/FlowCanvas.tsx index 469706f..2c55869 100644 --- a/src/components/FlowEditor/editor/FlowCanvas.tsx +++ b/src/components/FlowEditor/editor/FlowCanvas.tsx @@ -642,7 +642,7 @@ export const FlowCanvas: React.FC = ({ nodes, style={{ cursor: 'pointer' }} role="button" tabIndex={-1} - aria-label={t('flowCanvas.verbindungAuswaehlenEntfZumLoeschen')} + aria-label={t('Verbindung auswählen, Entf zum Löschen')} > = ({ nodes, pointerEvents="none" /> {isWarning && !isSelected && ( - {t('flowCanvas.typeMismatchWarningOutputType')} + {t('Typeninkompatibilität: Ausgabetyp')} )} ); @@ -760,8 +760,8 @@ export const FlowCanvas: React.FC = ({ nodes, outputLabel ?? (selectedConnectionId && !isOutput ? used - ? t('flowCanvas.aktuellesZielKlickenZumAbwaehlen') - : t('flowCanvas.klickenZumUmleiten') + ? t('Aktuelles Ziel klicken, um abzuwählen') + : t('Klicken zum Umleiten') : undefined) } /> @@ -840,7 +840,7 @@ export const FlowCanvas: React.FC = ({ nodes, )} {nodes.length === 0 && (
-

{t('flowCanvas.nodesAusDerListeLinks')}

+

{t('Nodes aus der Liste links')}

)} diff --git a/src/components/FlowEditor/editor/NodeConfigPanel.tsx b/src/components/FlowEditor/editor/NodeConfigPanel.tsx index 28fd6f4..0bbcec9 100644 --- a/src/components/FlowEditor/editor/NodeConfigPanel.tsx +++ b/src/components/FlowEditor/editor/NodeConfigPanel.tsx @@ -82,13 +82,13 @@ export const NodeConfigPanel: React.FC = ({ node,
{showNameField && (
- + onNodeUpdate(node.id, { title: e.target.value })} - placeholder={t('nodeConfigPanel.zbKundenformularPruefenLand')} + placeholder={t('z.B. Kundenformular prüfen, Land')} />

Wird im Data Picker angezeigt, um diesen Node zu identifizieren. diff --git a/src/components/FlowEditor/editor/NodeSidebar.tsx b/src/components/FlowEditor/editor/NodeSidebar.tsx index 4797bcd..2e248a3 100644 --- a/src/components/FlowEditor/editor/NodeSidebar.tsx +++ b/src/components/FlowEditor/editor/NodeSidebar.tsx @@ -88,7 +88,7 @@ export const NodeSidebar: React.FC = ({ nodeTypes, onFilterChange(e.target.value)} /> diff --git a/src/components/FlowEditor/editor/RunTracingPanel.tsx b/src/components/FlowEditor/editor/RunTracingPanel.tsx index 1710bb9..254bdf6 100644 --- a/src/components/FlowEditor/editor/RunTracingPanel.tsx +++ b/src/components/FlowEditor/editor/RunTracingPanel.tsx @@ -183,7 +183,7 @@ export const RunTracingPanel: React.FC = ({ Run Steps {loading && (loading...)}

{steps.length === 0 && !loading && ( -
{t('runTracingPanel.noStepsRecordedYet')}
+
{t('Noch keine Schritte aufgezeichnet')}
)} {steps.map((step: any) => { const startStr = _formatTimestamp(step.startedAt); @@ -222,7 +222,7 @@ export const RunTracingPanel: React.FC = ({ {step.retryCount > 0 && ( - + {step.retryCount}x retry )} diff --git a/src/components/FlowEditor/editor/WorkflowConfigurationModal.tsx b/src/components/FlowEditor/editor/WorkflowConfigurationModal.tsx index 2c137e8..d77ebb3 100644 --- a/src/components/FlowEditor/editor/WorkflowConfigurationModal.tsx +++ b/src/components/FlowEditor/editor/WorkflowConfigurationModal.tsx @@ -15,10 +15,10 @@ import { useLanguage } from '../../../providers/language/LanguageContext'; /** Vier Einstiege; bei „Immer aktiv“ folgt später die Listener-Konfiguration (E-Mail, Webhook, …). */ function _getKindOptions(t: (key: string) => string): { value: string; label: string }[] { return [ - { value: 'manual', label: t('workflowConfigurationModal.manuellerTrigger') }, - { value: 'form', label: t('workflowConfigurationModal.formular') }, - { value: 'schedule', label: t('workflowConfigurationModal.zeitplan') }, - { value: 'always_on', label: t('workflowConfigurationModal.immerAktiv') }, + { value: 'manual', label: t('Manueller Trigger') }, + { value: 'form', label: t('Formular') }, + { value: 'schedule', label: t('Zeitplan') }, + { value: 'always_on', label: t('Immer aktiv') }, ]; } @@ -89,7 +89,7 @@ export const WorkflowConfigurationModal: React.FC setTitleDe(e.target.value)} - placeholder={t('workflowConfigurationModal.zBAngebotAnlegen')} + placeholder={t('z.B. Angebot anlegen')} />
diff --git a/src/components/FlowEditor/nodes/form/FormNodeConfig.tsx b/src/components/FlowEditor/nodes/form/FormNodeConfig.tsx index eb071e9..8d8c3ae 100644 --- a/src/components/FlowEditor/nodes/form/FormNodeConfig.tsx +++ b/src/components/FlowEditor/nodes/form/FormNodeConfig.tsx @@ -76,7 +76,7 @@ export const FormNodeConfig: React.FC = ({ params,
{ e.dataTransfer.setData('text/plain', String(i)); @@ -133,8 +133,8 @@ export const FormNodeConfig: React.FC = ({ params, - - + +
))} - +
); }; @@ -260,7 +260,7 @@ const FieldBuilderEditor: React.FC = ({ param, value, onChan
))} - + ); }; @@ -285,7 +285,7 @@ const KeyValueRowsEditor: React.FC = ({ param, value, onChan ))} - + ); }; @@ -302,7 +302,7 @@ const CronBuilder: React.FC = ({ param, value, onChange }) = placeholder={t('index.5')} style={{ width: '100%', padding: '4px 8px', borderRadius: 4, border: '1px solid #ccc', fontFamily: 'monospace' }} /> -

{t('index.cronMinHourDayMonth')}

+

{t('Cron: Min Stunde Tag Monat')}

); }; @@ -317,14 +317,14 @@ const ConditionBuilder: React.FC = ({ param, value, onChange
update('value', e.target.value)} style={{ flex: 2, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} />
@@ -347,13 +347,13 @@ const MappingTableEditor: React.FC = ({ param, value, onChan {mappings.map((m: Record, i: number) => (
- updateMapping(i, 'sourceField', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} /> + updateMapping(i, 'sourceField', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} /> - updateMapping(i, 'outputField', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} /> + updateMapping(i, 'outputField', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} />
))} - + ); }; @@ -369,13 +369,13 @@ const FilterExpressionEditor: React.FC = ({ param, value, on update('field', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} /> update('value', e.target.value)} style={{ flex: 1, padding: '2px 4px', borderRadius: 4, border: '1px solid #ccc' }} /> diff --git a/src/components/FlowEditor/nodes/ifElse/IfElseNodeConfig.tsx b/src/components/FlowEditor/nodes/ifElse/IfElseNodeConfig.tsx index 46620cc..a19d1fd 100644 --- a/src/components/FlowEditor/nodes/ifElse/IfElseNodeConfig.tsx +++ b/src/components/FlowEditor/nodes/ifElse/IfElseNodeConfig.tsx @@ -100,7 +100,7 @@ export const IfElseNodeConfig: React.FC = ({ params, up
- +
@@ -120,7 +120,7 @@ export const IfElseNodeConfig: React.FC = ({ params, up value={String(value ?? '')} onChange={(e) => handleValueChange(e.target.value)} > - + {mimeTypeOptions.map((o) => (
{t('accessRulesTable.objektDotnotation')}{t('object dot notation')} View{t('accessRulesTable.eigeneM')}{t('accessRulesTable.gruppeG')}{t('accessRulesTable.alleA')}{t('own')}{t('group')}{t('Alle')}C R UDD C R UDD C R UDD
- + {voiceMap.map(entry => ( @@ -263,7 +263,7 @@ const VoiceSettingsTab: React.FC = () => { ))} @@ -273,7 +273,7 @@ const VoiceSettingsTab: React.FC = () => {
- +
- +
- + @@ -297,7 +297,7 @@ const VoiceSettingsTab: React.FC = () => { ); @@ -358,14 +358,14 @@ const NeutralizationMappingsTab: React.FC = () => { return text.slice(0, 2) + '*'.repeat(Math.min(text.length - 4, 20)) + text.slice(-2); }; - if (loading) return
{t('settings.mappingsWerdenGeladen')}
; + if (loading) return
{t('Mappings werden geladen')}
; return ( <> {error &&
{error}
}
-

{t('settings.platzhaltermappingsLokal')}

+

{t('Platzhaltermappings lokal')}

{ }} > AI-Workspace: Neutralisierter Chat-Text, Dokumente und Platzhalter-Mappings finden Sie unter{' '} - {t('settings.mandantAiworkspaceinstanzEinstellungenTabNeutralisierung')} (nicht auf dieser + {t('Mandant AI-Workspace-Instanz Einstellungen Tab Neutralisierung')} (nicht auf dieser Seite). Dieser Tab zeigt nur die lokale Liste über /api/local/neutralization-mappings.

@@ -488,8 +488,8 @@ export const SettingsPage: React.FC = () => { return (

-

{t('settings.einstellungen')}

-

{t('settings.persoenlicheEinstellungenUndPraeferenzen')}

+

{t('Einstellungen')}

+

{t('Persönliche Einstellungen und Präferenzen')}

@@ -173,11 +170,11 @@ const StorePage: React.FC = () => { {loading ? (
- {t('store.ladeFeatures', t('store.loadingFeatures'))} + {t('Lade Features…')}
) : features.length === 0 ? (
- {t('store.keineFeaturesImStoreVerfuegbar', t('store.noFeaturesAvailableInThe'))} + {t('Keine Features im Store verfügbar.')}
) : (
diff --git a/src/pages/admin/AccessManagementHub.tsx b/src/pages/admin/AccessManagementHub.tsx index 214fefd..df428f5 100644 --- a/src/pages/admin/AccessManagementHub.tsx +++ b/src/pages/admin/AccessManagementHub.tsx @@ -341,7 +341,7 @@ export const AccessManagementHub: React.FC = () => { value={selectedMandateId} onChange={(e) => setSelectedMandateId(e.target.value)} > - + {mandates.map((m) => ( + {features.map((f) => (
@@ -462,7 +462,7 @@ export const AccessManagementHub: React.FC = () => { {loading || statsLoading ? '…' : overviewStats.roles} - {t('accessManagementHub.rollenMax')} + {t('Rollen (max)')}
{relationshipData && relationshipData.instances.length > 0 && ( @@ -495,12 +495,12 @@ export const AccessManagementHub: React.FC = () => { {loading && filteredInstances.length === 0 ? (
- {t('accessManagementHub.ladeInstanzen')} + {t('Lade Instanzen')}
) : filteredInstances.length === 0 ? (
-

{t('accessManagementHub.keineFeatureinstanzen')}

+

{t('Keine Feature-Instanzen')}

Erstellen Sie eine neue Instanz oder wählen Sie ein anderes Feature.

@@ -521,7 +521,7 @@ export const AccessManagementHub: React.FC = () => { - {inst.enabled ? t('accessManagementHub.aktiv') : t('accessManagementHub.inaktiv')} + {inst.enabled ? t('Aktiv') : t('Inaktiv')}
@@ -542,7 +542,7 @@ export const AccessManagementHub: React.FC = () => { className={hubStyles.cardAction} onClick={() => handleSyncRoles(inst)} disabled={!inst.enabled} - title={t('accessManagementHub.rollenSynchronisieren')} + title={t('Rollen synchronisieren')} > Rollen sync diff --git a/src/pages/admin/AdminFeatureAccessPage.tsx b/src/pages/admin/AdminFeatureAccessPage.tsx index 85fb2b7..26c59ee 100644 --- a/src/pages/admin/AdminFeatureAccessPage.tsx +++ b/src/pages/admin/AdminFeatureAccessPage.tsx @@ -89,8 +89,8 @@ export const AdminFeatureAccessPage: React.FC = () => { // Table columns const columns = useMemo(() => [ - { key: 'label', label: t('adminFeatureAccess.name'), type: 'string' as const, sortable: true, filterable: true, searchable: true, width: 200 }, - { key: 'featureCode', label: t('adminFeatureAccess.feature'), type: 'string' as const, sortable: true, filterable: true, width: 150, + { key: 'label', label: t('Name'), type: 'string' as const, sortable: true, filterable: true, searchable: true, width: 200 }, + { key: 'featureCode', label: t('Feature'), type: 'string' as const, sortable: true, filterable: true, width: 150, render: (value: string) => { const feature = features.find(f => f.code === value); if (feature) { @@ -99,7 +99,7 @@ export const AdminFeatureAccessPage: React.FC = () => { return value; } }, - { key: 'enabled', label: t('adminFeatureAccess.aktiv'), type: 'boolean' as const, sortable: true, filterable: true, width: 80 }, + { key: 'enabled', label: t('Aktiv'), type: 'boolean' as const, sortable: true, filterable: true, width: 80 }, ], [features, t]); // Form attributes from backend - merge with dynamic feature options @@ -349,7 +349,7 @@ export const AdminFeatureAccessPage: React.FC = () => {

Feature-Instanzen

-

{t('adminFeatureAccess.verwaltenSieFeatureinstanzenFuerJeden')}

+

{t('Verwalten Sie Feature-Instanzen für jeden')}

@@ -365,7 +365,7 @@ export const AdminFeatureAccessPage: React.FC = () => { value={selectedMandateId} onChange={(e) => setSelectedMandateId(e.target.value)} > - + {mandates.map(m => (
{t('settings.sprache')}{t('settings.stimme')}
{t('Sprache')}{t('Stimme')}
- +
- - + + @@ -567,7 +567,7 @@ export const AdminMandateRolePermissionsPage: React.FC = () => { {templateFixResult && templateFixResult.invalidAssignments === 0 && (
- {t('adminMandateRolePermissions.keineFehlerhaftenTemplaterollenzuweisungen')} + {t('Keine fehlerhaften Templaterollenzuweisungen')}
)} @@ -576,7 +576,7 @@ export const AdminMandateRolePermissionsPage: React.FC = () => {
{cleanupPhase === 'preview' && cleanupResult && (cleanupResult.duplicateRulesToDelete > 0 || (templateFixResult && templateFixResult.invalidAssignments > 0)) && (
- +
@@ -405,7 +405,7 @@ export const AdminMandateRolesPage: React.FC = () => { {!selectedMandateId ? (
-

{t('adminMandateRoles.keinMandantAusgewaehlt')}

+

{t('Kein Mandant ausgewählt')}

Wählen Sie einen Mandanten aus, um dessen Rollen zu verwalten.

@@ -427,12 +427,12 @@ export const AdminMandateRolesPage: React.FC = () => { { type: 'edit' as const, onAction: handleEditClick, - title: t('adminMandateRolesPage.editRole'), + title: t('Rolle bearbeiten'), disabled: (row: Role) => row.isSystemRole ? { disabled: true, message: 'System-Rollen können nicht bearbeitet werden' } : false }, { type: 'delete' as const, - title: t('adminMandateRolesPage.deleteRole'), + title: t('Rolle löschen'), disabled: (row: Role) => row.isSystemRole ? { disabled: true, message: 'System-Rollen können nicht gelöscht werden' } : false } ]} @@ -442,7 +442,7 @@ export const AdminMandateRolesPage: React.FC = () => { pagination: pagination, handleDelete: handleDeleteRole, }} - emptyMessage={t('adminMandateRoles.keineRollenGefunden')} + emptyMessage={t('Keine Rollen gefunden')} />
)} @@ -452,7 +452,7 @@ export const AdminMandateRolesPage: React.FC = () => {
setShowCreateModal(false)}>
e.stopPropagation()}>
-

{t('adminMandateRoles.neueRolleErstellen')}

+

{t('Neue Rolle erstellen')}

@@ -254,7 +254,7 @@ export const AdminMandatesPage: React.FC = () => {
setShowCreateModal(false)}>
e.stopPropagation()}>
-

{t('adminMandates.neuerMandant')}

+

{t('Neuer Mandant')}

)} -

{t('adminUserAccessOverview.zugriffNachMandant')}

+

{t('Zugriff nach Mandant')}

{overview.mandates.length === 0 ? ( -

{t('adminUserAccessOverview.keineMandatezuordnungenVorhanden')}

+

{t('Keine Mandatszuordnungen vorhanden')}

) : (
{overview.mandates.map((mandate) => { @@ -232,7 +232,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => { {expandedMandates.has(mandate.id) && (
{mandateRoles.length === 0 ? ( -

{t('adminUserAccessOverview.keineRollenDirektAmMandanten')}

+

{t('Keine Rollen direkt am Mandanten')}

) : (
    {mandateRoles.map((r) => ( @@ -257,7 +257,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
    Feature-Instanzen
    {mandate.featureInstances.length === 0 ? ( -

    {t('adminUserAccessOverview.keineFeatureinstanzenZugewiesen')}

    +

    {t('Keine Feature-Instanzen zugewiesen')}

    ) : (
    {mandate.featureInstances.map((instance) => { @@ -338,7 +338,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => {

    - {t('adminUserAccessOverview.beschreibung')} {_roleDescriptionLine(role) || '—'} + {t('Beschreibung')} {_roleDescriptionLine(role) || '—'}

    @@ -359,13 +359,13 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
    - {t('adminUserAccessOverview.uizugriffsrechteBestimmenWelcheSeitenUnd')} + {t('UI-Zugriffsrechte bestimmen, welche Seiten und')}
    {overview.uiAccess.length === 0 ? (
    -

    {t('adminUserAccessOverview.keineUiberechtigungen')}

    +

    {t('Keine UI-Berechtigungen')}

    Diesem Benutzer wurden keine expliziten UI-Berechtigungen zugewiesen.

    @@ -376,7 +376,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
- + @@ -426,7 +426,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => { {overview.dataAccess.length === 0 ? (
-

{t('adminUserAccessOverview.keineDatenberechtigungen')}

+

{t('Keine Datenberechtigungen')}

Diesem Benutzer wurden keine expliziten Daten-Berechtigungen zugewiesen.

@@ -437,10 +437,10 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
- + - - + + @@ -522,13 +522,13 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
- {t('adminUserAccessOverview.ressourcenzugriffsrechteBestimmenWelcheSystemressourcenZb')} + {t('Ressourcenzugriffsrechte bestimmen, welche Systemressourcen z.B.')}
{overview.resourceAccess.length === 0 ? (
-

{t('adminUserAccessOverview.keineRessourcenberechtigungen')}

+

{t('Keine Ressourcenberechtigungen')}

Diesem Benutzer wurden keine expliziten Ressourcen-Berechtigungen zugewiesen.

@@ -539,7 +539,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
- + @@ -594,8 +594,8 @@ export const AdminUserAccessOverviewPage: React.FC = () => {
-

{t('adminUserAccessOverview.benutzerzugriffsuebersicht')}

-

{t('adminUserAccessOverview.zeigtAlleBerechtigungenEinesBenutzers')}

+

{t('Benutzerzugriffsübersicht')}

+

{t('Zeigt alle Berechtigungen eines Benutzers')}

@@ -613,7 +613,7 @@ export const AdminUserAccessOverviewPage: React.FC = () => { disabled={loadingUsers} style={{ minWidth: '300px' }} > - + {users.map(user => (
{t('adminMandateRolePermissions.rolle')}{t('adminMandateRolePermissions.mandant')}{t('Rolle')}{t('Mandant')} Aktion
UI-Element Sichtbar{t('adminUserAccessOverview.gewaehrtDurch')}{t('Gewährt durch')}
Tabelle/Feld Lesen{t('adminUserAccessOverview.erstellen')}{t('Erstellen')} Update{t('adminUserAccessOverview.loeschen')}{t('adminUserAccessOverview.gewaehrtDurch')}{t('Löschen')}{t('Gewährt durch')}
Ressource Zugriff{t('adminUserAccessOverview.gewaehrtDurch')}{t('Gewährt durch')}
- + {roles.map((r) => ( ))} - + @@ -113,7 +113,7 @@ export const PermissionMatrix: React.FC = ({ users, className={matrixStyles.actionBtn} onClick={() => onEditUser(user)} disabled={disabled} - title={t('permissionMatrix.rollenBearbeiten')} + title={t('Rollen bearbeiten')} > @@ -122,7 +122,7 @@ export const PermissionMatrix: React.FC = ({ users, className={`${matrixStyles.actionBtn} ${matrixStyles.actionBtnDanger}`} onClick={() => handleRemove(user)} disabled={disabled || removingId === user.userId} - title={t('permissionMatrix.ausInstanzEntfernen')} + title={t('Aus Instanz entfernen')} > diff --git a/src/pages/admin/wizards/AdminInvitationWizardPage.tsx b/src/pages/admin/wizards/AdminInvitationWizardPage.tsx index 36effa2..8cc8248 100644 --- a/src/pages/admin/wizards/AdminInvitationWizardPage.tsx +++ b/src/pages/admin/wizards/AdminInvitationWizardPage.tsx @@ -173,17 +173,17 @@ export const AdminInvitationWizardPage: React.FC = () => { const email = inviteeForm.email.trim(); const username = inviteeForm.username.trim(); if (!email && !username) { - setError(t('adminInvitationWizard.bitteMindestensEineEmailadresseOder')); + setError(t('Bitte mindestens eine E-Mail-Adresse oder')); return; } const emailLower = email.toLowerCase(); const userLower = username.toLowerCase(); if (email && invitees.some(i => !i.isExisting && (i.email || '').toLowerCase() === emailLower)) { - setError(t('adminInvitationWizard.dieseEmailIstBereitsIn')); + setError(t('Diese E-Mail ist bereits in')); return; } if (username && invitees.some(i => !i.isExisting && (i.username || '').toLowerCase() === userLower)) { - setError(t('adminInvitationWizard.dieserBenutzernameIstBereitsIn')); + setError(t('Dieser Benutzername ist bereits in')); return; } setInvitees(prev => [...prev, { @@ -198,14 +198,14 @@ export const AdminInvitationWizardPage: React.FC = () => { const addInviteeExisting = () => { if (!selectedExistingUserId) { - setError(t('adminInvitationWizard.bitteWaehlenSieEinenBenutzer')); + setError(t('Bitte wählen Sie einen Benutzer')); return; } const user = allSystemUsers.find(u => u.id === selectedExistingUserId); if (!user) return; const email = (user.email || '').trim(); if (invitees.some(i => i.userId === user.id)) { - setError(t('adminInvitationWizard.dieserBenutzerIstBereitsIn')); + setError(t('Dieser Benutzer ist bereits in')); return; } setInvitees(prev => [...prev, { @@ -235,7 +235,7 @@ export const AdminInvitationWizardPage: React.FC = () => { const handleSend = async () => { if (!selectedMandate || invitees.length === 0) return; if (inviteType === 'featureInstance' && !selectedInstance) { - setError(t('adminInvitationWizard.bitteWaehlenSieEineFeatureinstanz')); + setError(t('Bitte wählen Sie eine Feature-Instanz')); return; } setIsLoading(true); @@ -357,7 +357,7 @@ export const AdminInvitationWizardPage: React.FC = () => { {/* ── STEP 1: Invite type ── */} {step === 1 && (
-

{t('adminInvitationWizard.wohinMoechtenSieEinladen')}

+

{t('Wohin möchten Sie einladen?')}

+
{t('permissionMatrix.benutzer')}{t('Benutzer')} {r.roleLabel} {t('permissionMatrix.aktiv')}{t('Aktiv')} Aktionen
- + - + @@ -645,12 +645,12 @@ export const AdminInvitationWizardPage: React.FC = () => {
{t('adminInvitationWizard.emailBenutzer')}{t('E-Mail Benutzer')} Benutzername{t('adminInvitationWizard.rollen')}{t('Rollen')} Typ Aktion
) : ( -

{t('adminInvitationWizard.nochKeineEinladungenHinzugefuegt')}

+

{t('Noch keine Einladungen hinzugefügt')}

)}
- + +