From 7f9f5b0539be92311abf00da864f778c9fb158be Mon Sep 17 00:00:00 2001 From: idittrich-valueon Date: Fri, 20 Jun 2025 10:20:43 +0200 Subject: [PATCH] added multilanguage setting --- src/App.tsx | 41 +- .../Dashboard/DashboardChat/DashboardChat.tsx | 10 +- .../DashbaordChatAreaStatusDisplay.tsx | 6 +- .../DashboardChatArea/DashboardChatArea.tsx | 5 +- .../DashboardChatAreaInput.tsx | 6 +- .../DashboardChatAreaMessageItem.tsx | 10 +- .../DashboardChatAreaMessageList.tsx | 13 +- .../FilePreviewPopup.module.css | 10 +- .../DashboardChatArea/FilePreviewPopup.tsx | 12 +- .../DashboardChatHistory.tsx | 14 +- .../DashboardChatHistoryItem.tsx | 30 +- .../Dashboard/DashboardLog/DashboardLog.tsx | 18 +- .../DashboardPrompt/DashboardPrompt.tsx | 16 +- .../DashboardPromptSet/DashboardPromptSet.tsx | 14 +- .../DashboardPromptSetItem.tsx | 18 +- .../DashboardPromptSetModal.tsx | 22 +- .../DashboardPromptSettings.tsx | 7 +- src/components/Dateien/DateienAll.tsx | 12 +- src/components/Dateien/DateienCreated.tsx | 12 +- .../DateienSelector.module.css | 34 +- .../DateienHinzufügen/DateienSelector.tsx | 34 +- .../DateienHinzufügen/DateienUploadTool.tsx | 24 +- src/components/Dateien/DateienItem.tsx | 82 +-- src/components/Dateien/DateienShared.tsx | 12 +- src/components/Dateien/DateienUploads.tsx | 12 +- src/components/Sidebar/SidebarData.tsx | 13 +- src/contexts/LanguageContext.tsx | 67 ++ src/contexts/languageContextData.ts | 626 ++++++++++++++++++ src/pages/Dateien/Dateien.tsx | 18 +- .../Einstellungen/Einstellungen.module.css | 34 + src/pages/Einstellungen/Einstellungen.tsx | 47 +- 31 files changed, 1049 insertions(+), 230 deletions(-) create mode 100644 src/contexts/LanguageContext.tsx create mode 100644 src/contexts/languageContextData.ts diff --git a/src/App.tsx b/src/App.tsx index 1b6228f..20c89fd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import Register from './pages/Register'; import { AuthProvider } from './auth/authProvider'; import { ProtectedRoute } from './auth/ProtectedRoute'; +import { LanguageProvider } from './contexts/LanguageContext'; import Home from './pages/Home'; import Dateien from './pages/Dateien/Dateien'; import TeamBereich from './pages/TeamBereich/TeamBereich'; @@ -33,25 +34,27 @@ function App() { document.documentElement.setAttribute('data-theme', prefersDark ? 'dark' : 'light'); }, []); return ( - - - - {/* Public route */} - } /> - } /> - - - - }> - } /> - } /> - } /> - } /> - - - - + + + + + {/* Public route */} + } /> + } /> + + + + }> + } /> + } /> + } /> + } /> + + + + + ); } diff --git a/src/components/Dashboard/DashboardChat/DashboardChat.tsx b/src/components/Dashboard/DashboardChat/DashboardChat.tsx index 76a4e36..1c90e5b 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChat.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChat.tsx @@ -2,6 +2,7 @@ import React, { useState } from "react"; import { BsArrowsAngleExpand, BsArrowsAngleContract } from "react-icons/bs"; import { motion, AnimatePresence } from "framer-motion"; import { Prompt } from "../../../hooks/usePrompts"; +import { useLanguage } from '../../../contexts/LanguageContext'; import DashboardChatArea from './DashboardChatArea/DashboardChatArea'; import DashboardChatHistory from './DashboardChatHistory/DashboardChatHistory'; @@ -27,12 +28,13 @@ const DashboardChat: React.FC = ({ onWorkflowCompletedChange, onWorkflowResume }) => { - const [activeTab, setActiveTab] = useState("Chatbereich"); + const { t } = useLanguage(); + const [activeTab, setActiveTab] = useState(t('dashboard.chat.area')); const [resumeWorkflowId, setResumeWorkflowId] = useState(null); const handleWorkflowResume = (workflowId: string) => { // Switch to Chat Area tab first - setActiveTab("Chatbereich"); + setActiveTab(t('dashboard.chat.area')); // Set the workflow ID to resume setResumeWorkflowId(workflowId); // Then call the parent's resume handler @@ -57,7 +59,7 @@ const DashboardChat: React.FC = ({ transition={{ duration: 0.3, ease: "easeOut" }} >
- {["Chatbereich", "Workflow-Verlauf"].map((tab) => ( + {[t('dashboard.chat.area'), t('dashboard.chat.history')].map((tab) => (
= ({ }} style={{ overflow: "hidden" }} > - {activeTab === "Chatbereich" ? ( + {activeTab === t('dashboard.chat.area') ? ( = ({ @@ -11,6 +12,7 @@ const WorkflowStatusDisplay: React.FC = ({ handleRetry, shouldShowRetryButton }) => { + const { t } = useLanguage(); return ( {currentWorkflowId && shouldShowRetryButton() && ( @@ -23,13 +25,13 @@ const WorkflowStatusDisplay: React.FC = ({ >
- Workflow failed. + {t('chat.workflow_failed')}
diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatArea.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatArea.tsx index ce64a4b..e842786 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatArea.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatArea.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from "react"; import { DashboardChatAreaProps } from "./dashboardChatAreaTypes"; import { useChatLogic } from "./dashboardChatAreaLogic"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import MessageList from "./DashboardChatAreaMessageList"; import ChatInput from "./DashboardChatAreaInput"; import styles from './DashboardChatArea.module.css'; @@ -53,6 +54,8 @@ const DashboardChatArea: React.FC = ({ resumeWorkflowId }); + const { t } = useLanguage(); + // Notify parent component when workflow completion status changes useEffect(() => { if (onWorkflowCompletedChange) { @@ -60,7 +63,7 @@ const DashboardChatArea: React.FC = ({ } }, [workflowCompleted, onWorkflowCompletedChange]); - const placeholder = workflowCompleted ? "Gespräch fortsetzen..." : "Nachricht eingeben..."; + const placeholder = workflowCompleted ? t('chat.continue_conversation') : t('chat.enter_message'); return (
diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaInput.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaInput.tsx index 814e3ef..f0cfc40 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaInput.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaInput.tsx @@ -5,6 +5,7 @@ import { FaStop } from "react-icons/fa"; import { IoAttach, IoClose } from "react-icons/io5"; import { ChatInputProps } from "./dashboardChatAreaTypes"; import { FileInfo } from "../../../../hooks/useFiles"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import DateienSelector from "../../../Dateien/DateienHinzufügen/DateienSelector"; import styles from './DashboardChatArea.module.css'; @@ -44,6 +45,7 @@ const ChatInput: React.FC = ({ onFileRemove, onFilesSelect }) => { + const { t } = useLanguage(); const [isUploadModalOpen, setIsUploadModalOpen] = useState(false); const [isDragOver, setIsDragOver] = useState(false); @@ -169,7 +171,7 @@ const ChatInput: React.FC = ({ @@ -203,7 +205,7 @@ const ChatInput: React.FC = ({ disabled={isDisabled || isWorkflowRunning} whileTap={{ scale: 0.95 }} transition={{ duration: 0.2, ease: "easeOut" }} - title="Datei anhängen" + title={t('chat.attach_file')} > diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageItem.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageItem.tsx index c0bbe85..ab99021 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageItem.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageItem.tsx @@ -4,6 +4,7 @@ import { MdOutlineRemoveRedEye } from "react-icons/md"; import { Message, Document } from "./dashboardChatAreaTypes"; import FilePreviewPopup from "./FilePreviewPopup"; import { useFileDownload } from "../../../../hooks/useWorkflows"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import styles from './DashboardChatArea.module.css'; interface MessageItemProps { @@ -62,6 +63,7 @@ const getFileIcon = (type?: string, ext?: string): string => { }; const MessageItem: React.FC = ({ message, index }) => { + const { t } = useLanguage(); const [previewDocument, setPreviewDocument] = useState(null); const [isPreviewOpen, setIsPreviewOpen] = useState(false); const { downloadFile, isDownloading, error: downloadError } = useFileDownload(); @@ -119,7 +121,7 @@ const MessageItem: React.FC = ({ message, index }) => { className={`${styles.message} ${styles[`message_${message.role}`]}`} >
- {message.role === 'user' ? 'You' : message.agentName} + {message.role === 'user' ? t('chat.you') : message.agentName}
{message.content} @@ -132,7 +134,7 @@ const MessageItem: React.FC = ({ message, index }) => { key={document.id || docIndex} className={styles.document_item} onClick={() => handleDocumentClick(document)} - title={`Click to open ${document.name}`} + title={`${t('chat.click_to_open')} ${document.name}`} > {getFileIcon(document.type, document.ext)} @@ -153,14 +155,14 @@ const MessageItem: React.FC = ({ message, index }) => { diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageList.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageList.tsx index 6e6f2ac..b926849 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageList.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/DashboardChatAreaMessageList.tsx @@ -3,6 +3,7 @@ import { motion } from "framer-motion"; import { MessageListProps } from "./dashboardChatAreaTypes"; import MessageItem from "./DashboardChatAreaMessageItem"; import WorkflowStatusDisplay from "./DashbaordChatAreaStatusDisplay"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import styles from './DashboardChatArea.module.css'; const MessageList: React.FC = ({ @@ -19,6 +20,8 @@ const MessageList: React.FC = ({ handleRetry, shouldShowRetryButton }) => { + const { t } = useLanguage(); + return ( = ({
{startingWorkflow && (
-

{workflowCompleted && currentWorkflowId ? 'Sending follow-up message...' : 'Sending message...'}

+

{workflowCompleted && currentWorkflowId ? t('chat.sending_followup', 'Sending follow-up message...') : t('chat.sending_message', 'Sending message...')}

)} {startError && (
-

Error: {startError}

+

{t('chat.error_prefix', 'Error:')} {startError}

)} {messagesError && (
-

Error loading messages: {messagesError}

+

{t('chat.error_loading_messages', 'Error loading messages:')} {messagesError}

)} {currentWorkflowId && messagesLoading && messages.length === 0 && (
-

Loading workflow messages...

+

{t('chat.loading_workflow_messages', 'Loading workflow messages...')}

)} {messages.length > 0 ? ( @@ -56,7 +59,7 @@ const MessageList: React.FC = ({ /> )) ) : !currentWorkflowId ? ( -

Beginne ein Gespräch, indem du eine Nachricht eingibst, eine Vorlage auswählst oder einen vorherigen Workflow fortsetzt …

+

{t('chat.start_conversation', 'Start a conversation by entering a message, selecting a template, or continuing a previous workflow...')}

) : null} {/* Spacer to push workflow status to bottom when there are fewer messages */} diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.module.css b/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.module.css index e290e97..1aece67 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.module.css +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.module.css @@ -4,7 +4,7 @@ left: 0; right: 0; bottom: 0; - background-color: rgba(0, 0, 0, 0.7); + background-color: var(--color-bg); display: flex; align-items: center; justify-content: center; @@ -134,7 +134,7 @@ .text_preview { width: 100%; height: 100%; - background-color: var(--color-surface); + background-color: var(--color-bg); border: 1px solid var(--color-gray-disabled); border-radius: 8px; padding: 16px; @@ -185,14 +185,14 @@ .text_numbered { margin: 8px 0; padding-left: 8px; - color: var(--color-gray); + color: var(--color-text); font-family: var(--font-family); } .text_bullet { margin: 4px 0; padding-left: 8px; - color: var(--color-gray); + color: var(--color-text); font-family: var(--font-family); } @@ -204,7 +204,7 @@ border-radius: 4px; font-family: 'Courier New', monospace; font-size: 0.9em; - color: var(--color-gray); + color: var(--color-text); } .code_preview { diff --git a/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.tsx b/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.tsx index 549e2d5..8685c4a 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatArea/FilePreviewPopup.tsx @@ -3,6 +3,7 @@ import ReactMarkdown from 'react-markdown'; import { MdClose } from "react-icons/md"; import { Document } from "./dashboardChatAreaTypes"; import { useFilePreview } from "../../../../hooks/useWorkflows"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import styles from './FilePreviewPopup.module.css'; interface FilePreviewPopupProps { @@ -12,6 +13,7 @@ interface FilePreviewPopupProps { } const FilePreviewPopup: React.FC = ({ document, isOpen, onClose }) => { + const { t } = useLanguage(); const { previewContent, fileMetadata, isLoading, error, fetchPreview, clearPreview } = useFilePreview(); useEffect(() => { @@ -38,13 +40,13 @@ const FilePreviewPopup: React.FC = ({ document, isOpen, o const getPreviewComponent = () => { if (isLoading) { - return
Loading preview...
; + return
{t('file_preview.loading')}
; } if (error) { return (
-
Error: {error}
+
{t('file_preview.error')}: {error}
{fileMetadata && (
Debug: {JSON.stringify(fileMetadata, null, 2)} @@ -57,7 +59,7 @@ const FilePreviewPopup: React.FC = ({ document, isOpen, o if (!previewContent) { return (
-
No preview available
+
{t('file_preview.no_preview')}
{fileMetadata && (
Available metadata: {Object.keys(fileMetadata).join(', ')} @@ -165,7 +167,7 @@ const FilePreviewPopup: React.FC = ({ document, isOpen, o return (
- Python + {t('file_preview.python')} {document.ext ? `${document.name}.${document.ext}` : document.name} @@ -229,7 +231,7 @@ const FilePreviewPopup: React.FC = ({ document, isOpen, o diff --git a/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistory.tsx b/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistory.tsx index 5b284b7..bd00f11 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistory.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistory.tsx @@ -1,6 +1,7 @@ import React from "react"; import { motion } from "framer-motion"; import { useWorkflows } from "../../../../hooks/useWorkflows"; +import { useLanguage } from "../../../../contexts/LanguageContext"; import DashboardChatHistoryItem from "./DashboardChatHistoryItem"; import styles from './DashboardChatHistory.module.css'; @@ -11,6 +12,7 @@ interface DashboardChatHistoryProps { const DashboardChatHistory: React.FC = ({ onWorkflowResume }) => { const { workflows, loading, error, refetch } = useWorkflows(); + const { t } = useLanguage(); const handleWorkflowResume = (workflowId: string) => { if (onWorkflowResume) { @@ -28,7 +30,7 @@ const DashboardChatHistory: React.FC = ({ onWorkflowR transition={{ delay: 0.2, duration: 0.3, ease: "easeOut" }} >
-
Workflows werden geladen...
+
{t('chat_history.loading', 'Loading workflows...')}
); @@ -43,12 +45,12 @@ const DashboardChatHistory: React.FC = ({ onWorkflowR transition={{ delay: 0.2, duration: 0.3, ease: "easeOut" }} >
-
Fehler beim Laden der Workflows: {error}
+
{t('chat_history.error_loading', 'Error loading workflows:')} {error}
@@ -64,16 +66,16 @@ const DashboardChatHistory: React.FC = ({ onWorkflowR >
-

Workflow-Verlauf

+

{t('chat_history.title', 'Workflow History')}

- {workflows.length} {workflows.length === 1 ? 'Workflow' : 'Workflows'} + {workflows.length} {workflows.length === 1 ? t('chat_history.workflow_count', 'Workflow') : t('chat_history.workflow_count_plural', 'Workflows')}
{workflows.length === 0 ? (
- Keine Workflows verfügbar + {t('chat_history.empty_state', 'No workflows available')}
) : (
diff --git a/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistoryItem.tsx b/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistoryItem.tsx index d3d1745..724b605 100644 --- a/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistoryItem.tsx +++ b/src/components/Dashboard/DashboardChat/DashboardChatHistory/DashboardChatHistoryItem.tsx @@ -3,6 +3,7 @@ import { FaArrowRight } from 'react-icons/fa'; import { AiOutlineDelete } from 'react-icons/ai'; import { motion } from 'framer-motion'; import { useWorkflowOperations, useWorkflowMessages, Workflow } from '../../../../hooks/useWorkflows'; +import { useLanguage } from '../../../../contexts/LanguageContext'; import styles from './DashboardChatHistoryItem.module.css'; interface DashboardChatHistoryItemProps { @@ -14,15 +15,17 @@ interface DashboardChatHistoryItemProps { function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardChatHistoryItemProps) { const { deleteWorkflow, deletingWorkflows } = useWorkflowOperations(); const { messages } = useWorkflowMessages(workflow.id); + const { t } = useLanguage(); const isDeleting = deletingWorkflows.has(workflow.id); // Get the first user message as preview const firstUserMessage = messages.find(msg => msg.role === 'user'); - const messagePreview = firstUserMessage?.content || 'No message content available'; + const messagePreview = firstUserMessage?.content || t('chat_history.no_message_content', 'No message content available'); const handleDelete = async () => { - if (window.confirm(`Are you sure you want to delete workflow "${workflow.id.substring(0, 8)}..."?`)) { + const confirmMessage = t('chat_history.confirm_delete', 'Are you sure you want to delete workflow "{id}..."?').replace('{id}', workflow.id.substring(0, 8)); + if (window.confirm(confirmMessage)) { const success = await deleteWorkflow(workflow.id); if (success && onDelete) { onDelete(); @@ -35,7 +38,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha }; const formatDate = (dateString?: string) => { - if (!dateString) return 'Unknown date'; + if (!dateString) return t('chat_history.unknown_date', 'Unknown date'); try { return new Date(dateString).toLocaleDateString('en-US', { year: 'numeric', @@ -45,7 +48,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha minute: '2-digit' }); } catch (error) { - return 'Invalid date'; + return t('chat_history.invalid_date', 'Invalid date'); } }; @@ -86,6 +89,11 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha return statusLower === 'running' || statusLower === 'processing'; }; + const getTranslatedStatus = (status: string): string => { + const statusKey = `status.${status.toLowerCase()}`; + return t(statusKey, status.toUpperCase()); + }; + const renderStatusIndicator = () => { if (isRunning(workflow.status)) { return ( @@ -118,7 +126,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha backgroundColor: getStatusBackgroundColor(workflow.status) }} > - {workflow.status.toUpperCase()} + {getTranslatedStatus(workflow.status)} ); } @@ -143,19 +151,19 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha {renderStatusIndicator()} {workflow.currentRound && ( - Round {workflow.currentRound} + {t('chat_history.round', 'Round')} {workflow.currentRound} )}
{workflow.startedAt && (

- Started: {formatDate(workflow.startedAt)} + {t('chat_history.started', 'Started:')} {formatDate(workflow.startedAt)}

)} {workflow.lastActivity && (

- Last Activity: {formatDate(workflow.lastActivity)} + {t('chat_history.last_activity', 'Last Activity:')} {formatDate(workflow.lastActivity)}

)}
@@ -175,7 +183,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha @@ -184,7 +192,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha onClick={handleDelete} disabled={isDeleting} className={`${styles.actionButton} ${styles.deleteButton}`} - title="Delete workflow" + title={t('chat_history.delete_tooltip', 'Delete workflow')} > @@ -193,7 +201,7 @@ function DashboardChatHistoryItem({ workflow, onDelete, onResume }: DashboardCha {isDeleting && (
- Deleting workflow... + {t('chat_history.deleting', 'Deleting workflow...')}
)}
diff --git a/src/components/Dashboard/DashboardLog/DashboardLog.tsx b/src/components/Dashboard/DashboardLog/DashboardLog.tsx index 78ad301..85326a7 100644 --- a/src/components/Dashboard/DashboardLog/DashboardLog.tsx +++ b/src/components/Dashboard/DashboardLog/DashboardLog.tsx @@ -3,6 +3,7 @@ import { motion } from "framer-motion"; import styles from './DashboardLog.module.css'; import { useApiRequest } from '../../../hooks/useApi'; +import { useLanguage } from '../../../contexts/LanguageContext'; interface DashboardLogProps { isExpanded: boolean; @@ -11,6 +12,7 @@ interface DashboardLogProps { } const DashboardLog: React.FC = ({ isExpanded, workflowId, workflowCompleted = false }) => { + const { t } = useLanguage(); const [logs, setLogs] = useState([]); const [isPolling, setIsPolling] = useState(false); const [logsError, setLogsError] = useState(null); @@ -33,7 +35,7 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor setLogsError(null); } catch (error: any) { console.error('Error fetching logs:', error); - setLogsError(error.message || 'Failed to fetch logs'); + setLogsError(error.message || t('dashboard.log.fetch_failed')); } }; @@ -108,7 +110,7 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor return (
$ - No workflow selected + {t('dashboard.log.no_workflow')}
); } @@ -117,7 +119,7 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor return (
$ - Loading logs... + {t('dashboard.log.loading')}
); } @@ -126,15 +128,15 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor return (
$ - Error loading logs: {logsError} + {t('dashboard.log.error')}: {logsError}
); } if (logs.length === 0) { const statusText = workflowCompleted - ? "No logs available for this workflow" - : "Workflow running... Waiting for logs..."; + ? t('dashboard.log.no_logs') + : t('dashboard.log.waiting'); return (
@@ -152,7 +154,7 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor {log.timestamp ? new Date(log.timestamp).toLocaleTimeString() : ''} - [{log.level || 'INFO'}] + [{log.level || t('dashboard.log.level.info')}] {log.message || log.content || JSON.stringify(log)}
))} @@ -177,7 +179,7 @@ const DashboardLog: React.FC = ({ isExpanded, workflowId, wor whileHover={{ scale: 1.05 }} transition={{ duration: 0.2, ease: "easeOut" }} > - Log {workflowId && `- Workflow ${workflowId.substring(0, 8)}...`} + {t('dashboard.log.title')} {workflowId && `- ${t('dashboard.log.workflow')} ${workflowId.substring(0, 8)}...`} = ({ isCollapsed, onToggleCollapse }) => { - const [activeTab, setActiveTab] = useState("Prompt Vorlage"); + const { t } = useLanguage(); + const [activeTab, setActiveTab] = useState(t('dashboard.prompt.template')); const [searchParams] = useSearchParams(); useEffect(() => { @@ -27,19 +29,19 @@ const DashboardPrompt: React.FC = ({ const promptId = searchParams.get('promptId'); if (expandedPrompt) { - setActiveTab("Prompt Vorlage"); + setActiveTab(t('dashboard.prompt.template')); } else if (promptId) { - setActiveTab("Einstellungen"); + setActiveTab(t('dashboard.prompt.settings')); } - }, [searchParams]); + }, [searchParams, t]); return (
{[ - "Prompt Vorlage", - "Einstellungen" + t('dashboard.prompt.template'), + t('dashboard.prompt.settings') ].map((tab) => (
); @@ -52,11 +54,11 @@ function DashboardPromptSet({ onPromptRun }: DashboardPromptSetProps) {
- {prompts.length} {prompts.length === 1 ? 'Prompt' : 'Prompts'} + {prompts.length} {prompts.length === 1 ? t('promptset.prompt_count') : t('promptset.prompt_count_plural')}
@@ -64,7 +66,7 @@ function DashboardPromptSet({ onPromptRun }: DashboardPromptSetProps) {
{prompts.length === 0 ? (
- Keine Prompts verfügbar + {t('promptset.no_prompts')}
) : (
diff --git a/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetItem.tsx b/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetItem.tsx index 135c241..af37274 100644 --- a/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetItem.tsx +++ b/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetItem.tsx @@ -3,6 +3,7 @@ import { FaArrowRight } from 'react-icons/fa'; import { AiOutlineDelete } from 'react-icons/ai'; import { BsShareFill } from 'react-icons/bs'; import { usePromptOperations, Prompt } from '../../../../hooks/usePrompts'; +import { useLanguage } from '../../../../contexts/LanguageContext'; import styles from './DashboardPromptSetItem.module.css'; interface DashboardPromptSetItemProps { @@ -12,6 +13,7 @@ interface DashboardPromptSetItemProps { } function DashboardPromptSetItem({ prompt, onDelete, onRun }: DashboardPromptSetItemProps) { + const { t } = useLanguage(); const { handlePromptDelete, deletingPrompts, deleteError } = usePromptOperations(); const contentRef = useRef(null); const [showDeleteConfirm, setShowDeleteConfirm] = useState(false); @@ -54,7 +56,7 @@ function DashboardPromptSetItem({ prompt, onDelete, onRun }: DashboardPromptSetI {prompt.createdAt && (

- Erstellt: {new Date(prompt.createdAt).toLocaleDateString('de-DE')} + {t('promptset.created')}: {new Date(prompt.createdAt).toLocaleDateString('de-DE')}

)}
@@ -70,7 +72,7 @@ function DashboardPromptSetItem({ prompt, onDelete, onRun }: DashboardPromptSetI @@ -78,7 +80,7 @@ function DashboardPromptSetItem({ prompt, onDelete, onRun }: DashboardPromptSetI @@ -87,25 +89,25 @@ function DashboardPromptSetItem({ prompt, onDelete, onRun }: DashboardPromptSetI onClick={handleDeleteClick} disabled={isDeleting} className={`${styles.actionButton} ${styles.deleteButton} ${showDeleteConfirm ? styles.confirm : ''}`} - title={showDeleteConfirm ? "Klicken Sie erneut zum Bestätigen" : "Prompt löschen"} + title={showDeleteConfirm ? t('promptset.confirm_delete') : t('promptset.delete_tooltip')} onBlur={handleCancelDelete} > - {isDeleting && Löschen...} - {showDeleteConfirm && Zum Bestätigen klicken} + {isDeleting && {t('promptset.deleting')}} + {showDeleteConfirm && {t('promptset.confirm_click')}}
{deleteError && (
- Fehler beim Löschen: {deleteError} + {t('promptset.delete_error')}: {deleteError}
)} {isDeleting && (
- Prompt wird gelöscht... + {t('promptset.deleting_message')}
)}
diff --git a/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetModal.tsx b/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetModal.tsx index 3e3cd9d..cc2789e 100644 --- a/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetModal.tsx +++ b/src/components/Dashboard/DashboardPrompt/DashboardPromptSet/DashboardPromptSetModal.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import { FaTimes } from 'react-icons/fa'; +import { useLanguage } from '../../../../contexts/LanguageContext'; import styles from './DashboardPromptSetModal.module.css'; interface DashboardPromptSetModalProps { @@ -10,6 +11,7 @@ interface DashboardPromptSetModalProps { } function DashboardPromptSetModal({ isOpen, onClose, onSubmit, isLoading = false }: DashboardPromptSetModalProps) { + const { t } = useLanguage(); const [name, setName] = useState(''); const [content, setContent] = useState(''); const [error, setError] = useState(null); @@ -18,12 +20,12 @@ function DashboardPromptSetModal({ isOpen, onClose, onSubmit, isLoading = false e.preventDefault(); if (!name.trim()) { - setError('Name ist erforderlich'); + setError(t('modal.name_required')); return; } if (!content.trim()) { - setError('Inhalt ist erforderlich'); + setError(t('modal.content_required')); return; } @@ -36,7 +38,7 @@ function DashboardPromptSetModal({ isOpen, onClose, onSubmit, isLoading = false setContent(''); onClose(); } catch (err: any) { - setError(err.message || 'Fehler beim Erstellen des Prompts'); + setError(err.message || t('modal.create_error')); } }; @@ -53,7 +55,7 @@ function DashboardPromptSetModal({ isOpen, onClose, onSubmit, isLoading = false
-

Neuen Prompt erstellen

+

{t('modal.create_prompt')}