diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/A2AMetrics.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/A2AMetrics.tsx index 2e0e5068297..8489be12511 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/A2AMetrics.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/A2AMetrics.tsx @@ -12,6 +12,7 @@ import { FileTextOutlined, RobotOutlined, } from "@ant-design/icons"; +import { useTranslation } from "react-i18next"; export interface A2ATaskMetadata { taskId?: string; @@ -80,6 +81,7 @@ const copyToClipboard = (text: string) => { }; const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, totalLatency }) => { + const { t } = useTranslation(); const [showDetails, setShowDetails] = useState(false); if (!a2aMetadata && !timeToFirstToken && !totalLatency) return null; @@ -92,7 +94,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* A2A Metadata Header */}
- A2A Metadata + {t("playground.a2AMetrics.header")}
{/* Main metrics row */} @@ -119,7 +121,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Latency */} {totalLatency !== undefined && ( - + {(totalLatency / 1000).toFixed(2)}s @@ -129,7 +131,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Time to first token */} {timeToFirstToken !== undefined && ( - + TTFT: {(timeToFirstToken / 1000).toFixed(2)}s )} @@ -139,13 +141,14 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken,
{/* Task ID */} {taskId && ( - + copyToClipboard(taskId)} > - Task: {truncateId(taskId)} + {t("playground.a2AMetrics.taskPrefix")} + {truncateId(taskId)} @@ -153,13 +156,14 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Context/Session ID */} {contextId && ( - + copyToClipboard(contextId)} > - Session: {truncateId(contextId)} + {t("playground.a2AMetrics.sessionPrefix")} + {truncateId(contextId)} @@ -174,7 +178,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, onClick={() => setShowDetails(!showDetails)} > {showDetails ? : } - Details + {t("playground.a2AMetrics.details")} )}
@@ -185,7 +189,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Status message */} {status?.message && (
- Status Message: + {t("playground.a2AMetrics.statusMessage")} {status.message}
)} @@ -193,7 +197,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Full IDs */} {taskId && (
- Task ID: + {t("playground.a2AMetrics.taskId")} {taskId} = ({ a2aMetadata, timeToFirstToken, {contextId && (
- Session ID: + {t("playground.a2AMetrics.sessionId")} {contextId} @@ -218,7 +222,7 @@ const A2AMetrics: React.FC = ({ a2aMetadata, timeToFirstToken, {/* Metadata fields */} {metadata && Object.keys(metadata).length > 0 && (
- Custom Metadata: + {t("playground.a2AMetrics.customMetadata")}
                 {JSON.stringify(metadata, null, 2)}
               
diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/AdditionalModelSettings.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/AdditionalModelSettings.tsx index 078c1b66afb..c7135d6f759 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/AdditionalModelSettings.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/AdditionalModelSettings.tsx @@ -2,6 +2,7 @@ import { InfoCircleOutlined } from "@ant-design/icons"; import { Text } from "@tremor/react"; import { Checkbox, InputNumber, Popover, Slider, Tooltip, Typography } from "antd"; import React, { useEffect, useState } from "react"; +import { Trans, useTranslation } from "react-i18next"; interface AdditionalModelSettingsProps { temperature?: number; @@ -51,6 +52,7 @@ const AdditionalModelSettings: React.FC = ({ onMaxTokensChange?.(newValue); }; + const { t } = useTranslation(); const disabledOpacity = useAdvancedParams ? 1 : 0.4; const disabledTextColor = useAdvancedParams ? "text-gray-700" : "text-gray-400"; @@ -65,13 +67,13 @@ const AdditionalModelSettings: React.FC = ({ return (
handleUseAdvancedParamsChange(e.target.checked)}> - Use Advanced Parameters + {t("playground.additionalModelSettings.useAdvancedParams")} {onMockTestFallbacksChange && (
onMockTestFallbacksChange(e.target.checked)}> - Simulate failure to test fallbacks + {t("playground.additionalModelSettings.simulateFailure")} = ({ content={
- Causes the first request to fail so the router tries fallbacks (if configured). Use this to verify - your fallback setup. + {t("playground.additionalModelSettings.simulateFailureDesc")} - Behavior can differ when keys, teams, or router settings are configured.{" "} - - Learn more - + + ), + }} + />
} >
@@ -108,8 +113,10 @@ const AdditionalModelSettings: React.FC = ({
- Temperature - + + {t("playground.additionalModelSettings.temperature")} + +
@@ -142,8 +149,10 @@ const AdditionalModelSettings: React.FC = ({
- Max Tokens - + + {t("playground.additionalModelSettings.maxTokens")} + +
diff --git a/ui/litellm-dashboard/src/components/playground/chat_ui/AgentBuilderView.tsx b/ui/litellm-dashboard/src/components/playground/chat_ui/AgentBuilderView.tsx index 8b0de5dda7c..fb5f72a09fe 100644 --- a/ui/litellm-dashboard/src/components/playground/chat_ui/AgentBuilderView.tsx +++ b/ui/litellm-dashboard/src/components/playground/chat_ui/AgentBuilderView.tsx @@ -11,6 +11,7 @@ import { } from "@ant-design/icons"; import { Button, Input, Modal, Select, Spin, Tabs } from "antd"; import React, { useCallback, useEffect, useState } from "react"; +import { Trans, useTranslation } from "react-i18next"; import CodeBlock from "@/app/(dashboard)/api-reference/components/CodeBlock"; import NotificationsManager from "../../molecules/notifications_manager"; import { keyCreateCall, modelCreateCall, modelDeleteCall, modelPatchUpdateCall, proxyBaseUrl } from "../../networking"; @@ -71,6 +72,7 @@ function ConnectTabContent({ createdKeyValue, onCreateKey, }: ConnectTabContentProps) { + const { t } = useTranslation(); const baseUrl = proxyBaseUrl ?? getConnectTabBaseUrl(proxySettings, customProxyBaseUrl); const apiKeyForCurl = createdKeyValue ? createdKeyValue.startsWith("Bearer ") @@ -95,31 +97,32 @@ function ConnectTabContent({ return (
-

Proxy base URL

+

{t("playground.agentBuilderView.proxyBaseUrl")}

{baseUrl}

-

Call your agent (cURL)

+

{t("playground.agentBuilderView.callYourAgent")}

-

Create a key for this agent

+

{t("playground.agentBuilderView.createKeyTitle")}

- Create a virtual key that can only call this agent. The key will be scoped to you (user_id) and restricted to - the model {agentName}. + }} + />

{disabledPersonalKeyCreation && ( -

Key creation is disabled for your account.

+

{t("playground.agentBuilderView.keyCreationDisabled")}

)} {createdKeyValue && ( -

- Key created. It is shown in the cURL example above — copy the snippet to use it. -

+

{t("playground.agentBuilderView.keyCreated")}

)}
@@ -180,6 +183,7 @@ export default function AgentBuilderView({ apiKey, customProxyBaseUrl, }: AgentBuilderViewProps) { + const { t } = useTranslation(); const [agentModels, setAgentModels] = useState([]); const [modelGroups, setModelGroups] = useState([]); const [loadingAgents, setLoadingAgents] = useState(true); @@ -220,7 +224,7 @@ export default function AgentBuilderView({ return list; } catch (e) { console.error(e); - NotificationsManager.fromBackend("Failed to load agents"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.failedToLoadAgents")); return []; } finally { setLoadingAgents(false); @@ -303,7 +307,7 @@ export default function AgentBuilderView({ const handleAddAgent = () => { setSelectedId(NEW_AGENT_ID); setDraftName(""); - setDraftSystemPrompt("You are a helpful assistant."); + setDraftSystemPrompt(t("playground.agentBuilderView.defaultSystemPrompt")); setDraftUnderlyingModel(modelGroups[0]?.model_group); setDraftTemperature(0.7); setDraftMaxTokens(4096); @@ -313,7 +317,7 @@ export default function AgentBuilderView({ const handleSaveAgent = async () => { if (!accessToken || !draftName?.trim() || !draftUnderlyingModel) { - NotificationsManager.fromBackend("Name and underlying model are required"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.nameAndModelRequired")); return; } setSaving(true); @@ -340,7 +344,7 @@ export default function AgentBuilderView({ setSelectedId(created ? getAgentSelectionKey(created) : list[0] ? getAgentSelectionKey(list[0]) : null); setActiveTab("chat"); } catch (e) { - NotificationsManager.fromBackend("Failed to save agent"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.failedToSaveAgent")); } finally { setSaving(false); } @@ -348,7 +352,7 @@ export default function AgentBuilderView({ const handleUpdateAgent = async () => { if (!accessToken || !selectedAgent || !selectedAgentModelId || !draftName?.trim() || !draftUnderlyingModel) { - NotificationsManager.fromBackend("Name and underlying model are required"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.nameAndModelRequired")); return; } setSaving(true); @@ -368,13 +372,13 @@ export default function AgentBuilderView({ }, selectedAgentModelId, ); - NotificationsManager.success("Agent updated successfully"); + NotificationsManager.success(t("playground.agentBuilderView.agentUpdated")); const list = await loadAgents(); const stillSelected = list.find((a) => getAgentModelId(a) === selectedAgentModelId); const target = stillSelected ?? list[0]; setSelectedId(target ? getAgentSelectionKey(target) : null); } catch (e) { - NotificationsManager.fromBackend("Failed to update agent"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.failedToUpdateAgent")); } finally { setSaving(false); } @@ -392,12 +396,12 @@ export default function AgentBuilderView({ const keyValue = response?.key ?? null; if (keyValue) { setCreatedKeyValue(keyValue); - NotificationsManager.success("Virtual key created. Use it in the curl example below."); + NotificationsManager.success(t("playground.agentBuilderView.virtualKeyCreated")); } else { - NotificationsManager.fromBackend("Key created but value not returned"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.keyCreatedNoValue")); } } catch (e) { - NotificationsManager.fromBackend("Failed to create key for agent"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.failedToCreateKey")); } finally { setCreatingKey(false); } @@ -406,21 +410,21 @@ export default function AgentBuilderView({ const handleDeleteAgent = () => { if (!selectedAgent || !selectedAgentModelId || !accessToken) return; Modal.confirm({ - title: "Delete agent", - content: `Are you sure you want to delete "${selectedAgent.model_name}"? This cannot be undone.`, - okText: "Delete", + title: t("playground.agentBuilderView.deleteAgentTitle"), + content: t("playground.agentBuilderView.deleteAgentConfirm", { name: selectedAgent.model_name }), + okText: t("common.delete"), okType: "danger", - cancelText: "Cancel", + cancelText: t("common.cancel"), onOk: async () => { setDeleting(true); try { await modelDeleteCall(accessToken, selectedAgentModelId); - NotificationsManager.success("Agent deleted"); + NotificationsManager.success(t("playground.agentBuilderView.agentDeleted")); const list = await loadAgents(); const remaining = list.filter((a) => getAgentModelId(a) !== selectedAgentModelId); setSelectedId(remaining.length > 0 ? getAgentSelectionKey(remaining[0]) : null); } catch (e) { - NotificationsManager.fromBackend("Failed to delete agent"); + NotificationsManager.fromBackend(t("playground.agentBuilderView.failedToDeleteAgent")); } finally { setDeleting(false); } @@ -430,7 +434,9 @@ export default function AgentBuilderView({ if (!accessToken || !userID || !userRole) { return ( -
Sign in to use Agent Builder.
+
+ {t("playground.agentBuilderView.signInRequired")} +
); } @@ -438,7 +444,7 @@ export default function AgentBuilderView({
- Agent Builder + {t("playground.agentBuilderView.title")} {isNewAgent ? ( ) : ( - Build Agents that pass your compliance requirements. + {t("playground.agentBuilderView.buildAgentsSubtitle")} )}
- Agent Builder is experimental and may change or be removed without notice. We’d love your feedback—email us - at{" "} - - product@berri.ai - - . + + ), + }} + />
@@ -470,8 +481,16 @@ export default function AgentBuilderView({ {/* Roster */}
- Agents -
{loadingAgents ? ( @@ -503,7 +522,7 @@ export default function AgentBuilderView({ onClick={handleAddAgent} className="mb-1 w-full rounded-md border border-dashed border-gray-300 px-3 py-2 text-left text-sm text-gray-500 hover:border-blue-400 hover:bg-blue-50/50 hover:text-gray-700" > - New agent + {t("playground.agentBuilderView.newAgent")} )} @@ -514,7 +533,7 @@ export default function AgentBuilderView({
{selectedId === null && !isNewAgent && agentModels.length === 0 && !loadingAgents && (
- No agents yet. Add an agent to get started. + {t("playground.agentBuilderView.noAgentsYet")}
)} {(selectedId !== null || isNewAgent) && ( @@ -528,7 +547,7 @@ export default function AgentBuilderView({ key: "configure", label: ( - Configure + {t("playground.agentBuilderView.tabConfigure")} ), children: ( @@ -537,40 +556,47 @@ export default function AgentBuilderView({
{!selectedAgentModelId && selectedAgent && (
- This agent cannot be updated or deleted here (missing model id). Manage it from Models - & Endpoints. + {t("playground.agentBuilderView.missingModelIdWarning")}
)}
- + setDraftName(e.target.value)} - placeholder="My Agent" + placeholder={t("playground.agentBuilderView.agentNamePlaceholder")} />
- +