From 77f006ff8e24c14e5493180b725c0236304352e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B9=E9=9B=AA?= <2b@yorha.xyz> Date: Thu, 11 Jun 2026 03:29:10 +0900 Subject: [PATCH] feat(ui): i18n for AI hub public forms and useful links --- .../AIHub/UsefulLinksManagement.tsx | 78 ++++++++------- .../AIHub/forms/MakeAgentPublicForm.tsx | 50 +++++----- .../AIHub/forms/MakeMCPPublicForm.tsx | 52 +++++----- .../AIHub/forms/MakeModelPublicForm.tsx | 48 +++++----- ui/litellm-dashboard/src/locales/en.json | 96 +++++++++++++++++++ ui/litellm-dashboard/src/locales/zh-CN.json | 96 +++++++++++++++++++ 6 files changed, 310 insertions(+), 110 deletions(-) diff --git a/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx b/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx index c73eaf52384..6cf57bb90d1 100644 --- a/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx +++ b/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx @@ -5,6 +5,7 @@ import { ChevronDownIcon, ChevronRightIcon, ExternalLinkIcon, PlusCircleIcon } f import { Card, Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow, Text, Title } from "@tremor/react"; import Link from "next/link"; import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; import { getProxyBaseUrl, getPublicModelHubInfo, updateUsefulLinksCall } from "../networking"; interface UsefulLinksManagementProps { @@ -20,6 +21,7 @@ interface Link { } const UsefulLinksManagement: React.FC = ({ accessToken, userRole }) => { + const { t } = useTranslation(); const [links, setLinks] = useState([]); const [newLink, setNewLink] = useState({ url: "", displayName: "" }); const [editingLink, setEditingLink] = useState(null); @@ -106,7 +108,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok return true; } catch (error) { console.error("Error saving links:", error); - NotificationsManager.fromBackend(`Failed to save links - ${error}`); + NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.saveLinksFailed", { error })); return false; } }; @@ -118,13 +120,13 @@ const UsefulLinksManagement: React.FC = ({ accessTok try { new URL(newLink.url); } catch { - NotificationsManager.fromBackend("Please enter a valid URL"); + NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.invalidUrl")); return; } // Check for duplicate display names if (links.some((link) => link.displayName === newLink.displayName)) { - NotificationsManager.fromBackend("A link with this display name already exists"); + NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.duplicateDisplayName")); return; } @@ -139,7 +141,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok if (await saveLinksToBackend(updatedLinks)) { setLinks(updatedLinks); setNewLink({ url: "", displayName: "" }); - NotificationsManager.success("Link added successfully"); + NotificationsManager.success(t("aiHub.usefulLinksManagement.addSuccess")); } }; @@ -154,13 +156,13 @@ const UsefulLinksManagement: React.FC = ({ accessTok try { new URL(editingLink.url); } catch { - NotificationsManager.fromBackend("Please enter a valid URL"); + NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.invalidUrl")); return; } // Check for duplicate display names (excluding current link) if (links.some((link) => link.id !== editingLink.id && link.displayName === editingLink.displayName)) { - NotificationsManager.fromBackend("A link with this display name already exists"); + NotificationsManager.fromBackend(t("aiHub.usefulLinksManagement.duplicateDisplayName")); return; } @@ -169,7 +171,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok if (await saveLinksToBackend(updatedLinks)) { setLinks(updatedLinks); setEditingLink(null); - NotificationsManager.success("Link updated successfully"); + NotificationsManager.success(t("aiHub.usefulLinksManagement.updateSuccess")); } }; @@ -182,7 +184,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok if (await saveLinksToBackend(updatedLinks)) { setLinks(updatedLinks); - NotificationsManager.success("Link deleted successfully"); + NotificationsManager.success(t("aiHub.usefulLinksManagement.deleteSuccess")); } }; @@ -208,7 +210,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok if (await saveLinksToBackend(links)) { setIsRearranging(false); setOriginalLinksOrder([]); - NotificationsManager.success("Link order saved successfully"); + NotificationsManager.success(t("aiHub.usefulLinksManagement.reorderSuccess")); } }; @@ -230,10 +232,8 @@ const UsefulLinksManagement: React.FC = ({ accessTok
setIsExpanded(!isExpanded)}>
- Link Management -

- Manage the links that are displayed under 'Useful Links' on the public model hub. -

+ {t("aiHub.usefulLinksManagement.title")} +

{t("aiHub.usefulLinksManagement.description")}

{isExpanded ? ( @@ -247,10 +247,14 @@ const UsefulLinksManagement: React.FC = ({ accessTok {isExpanded && (
- Add New Link + + {t("aiHub.usefulLinksManagement.addNewLink")} +
- + = ({ accessTok displayName: e.target.value, }) } - placeholder="Friendly name" + placeholder={t("aiHub.usefulLinksManagement.placeholderDisplayName")} className="w-full px-3 py-2 border border-gray-300 rounded-md text-sm" />
@@ -286,22 +290,24 @@ const UsefulLinksManagement: React.FC = ({ accessTok className={`flex items-center px-4 py-2 rounded-md text-sm ${!newLink.url || !newLink.displayName ? "bg-gray-300 text-gray-500 cursor-not-allowed" : "bg-green-600 text-white hover:bg-green-700"}`} > - Add Link + {t("aiHub.usefulLinksManagement.addLink")}
- Manage Existing Links + + {t("aiHub.usefulLinksManagement.manageExistingLinks")} +
- Public Model Hub + {t("aiHub.usefulLinksManagement.publicModelHub")} {!isRearranging ? ( @@ -309,7 +315,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok onClick={handleStartRearranging} className="text-xs bg-purple-50 text-purple-600 px-3 py-1.5 rounded hover:bg-purple-100 flex items-center" > - Rearrange Order + {t("aiHub.usefulLinksManagement.rearrangeOrder")} ) : (
@@ -317,13 +323,13 @@ const UsefulLinksManagement: React.FC = ({ accessTok onClick={handleSaveRearranging} className="text-xs bg-green-600 text-white px-3 py-1.5 rounded hover:bg-green-700" > - Save Order + {t("aiHub.usefulLinksManagement.saveOrder")}
)} @@ -334,9 +340,11 @@ const UsefulLinksManagement: React.FC = ({ accessTok - Display Name + + {t("aiHub.usefulLinksManagement.colDisplayName")} + URL - Actions + {t("common.actions")} @@ -376,13 +384,13 @@ const UsefulLinksManagement: React.FC = ({ accessTok onClick={handleUpdateLink} className="text-xs bg-blue-50 text-blue-600 px-2 py-1 rounded hover:bg-blue-100" > - Save + {t("common.save")} @@ -397,17 +405,17 @@ const UsefulLinksManagement: React.FC = ({ accessTok handleMoveUp(index)} - tooltipText="Move up" + tooltipText={t("aiHub.usefulLinksManagement.tooltipMoveUp")} disabled={index === 0} - disabledTooltipText="Already at the top" + disabledTooltipText={t("aiHub.usefulLinksManagement.tooltipAlreadyAtTop")} dataTestId={`move-up-${link.id}`} /> handleMoveDown(index)} - tooltipText="Move down" + tooltipText={t("aiHub.usefulLinksManagement.tooltipMoveDown")} disabled={index === links.length - 1} - disabledTooltipText="Already at the bottom" + disabledTooltipText={t("aiHub.usefulLinksManagement.tooltipAlreadyAtBottom")} dataTestId={`move-down-${link.id}`} /> @@ -416,19 +424,19 @@ const UsefulLinksManagement: React.FC = ({ accessTok setCurrentLink(link.url)} - tooltipText="Open link" + tooltipText={t("aiHub.usefulLinksManagement.tooltipOpenLink")} dataTestId={`open-link-${link.id}`} /> handleEditLink(link)} - tooltipText="Edit link" + tooltipText={t("aiHub.usefulLinksManagement.tooltipEditLink")} dataTestId={`edit-link-${link.id}`} /> deleteLink(link.id)} - tooltipText="Delete link" + tooltipText={t("aiHub.usefulLinksManagement.tooltipDeleteLink")} dataTestId={`delete-link-${link.id}`} /> @@ -441,7 +449,7 @@ const UsefulLinksManagement: React.FC = ({ accessTok {links.length === 0 && ( - No links added yet. Add a new link above. + {t("aiHub.usefulLinksManagement.noLinks")} )} diff --git a/ui/litellm-dashboard/src/components/AIHub/forms/MakeAgentPublicForm.tsx b/ui/litellm-dashboard/src/components/AIHub/forms/MakeAgentPublicForm.tsx index a38950b8fb7..752cc7acf6e 100644 --- a/ui/litellm-dashboard/src/components/AIHub/forms/MakeAgentPublicForm.tsx +++ b/ui/litellm-dashboard/src/components/AIHub/forms/MakeAgentPublicForm.tsx @@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react"; import { makeAgentsPublicCall } from "../../networking"; import NotificationsManager from "../../molecules/notifications_manager"; import { AgentHubData } from "@/components/AIHub/AgentHubTableColumns"; +import { useTranslation, Trans } from "react-i18next"; const { Step } = Steps; @@ -22,6 +23,7 @@ const MakeAgentPublicForm: React.FC = ({ agentHubData, onSuccess, }) => { + const { t } = useTranslation(); const [currentStep, setCurrentStep] = useState(0); const [selectedAgents, setSelectedAgents] = useState>(new Set()); const [loading, setLoading] = useState(false); @@ -37,7 +39,7 @@ const MakeAgentPublicForm: React.FC = ({ const handleNext = () => { if (currentStep === 0) { if (selectedAgents.size === 0) { - NotificationsManager.fromBackend("Please select at least one agent to make public"); + NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.selectAtLeastOne")); return; } setCurrentStep(1); @@ -83,7 +85,7 @@ const MakeAgentPublicForm: React.FC = ({ const handleSubmit = async () => { if (selectedAgents.size === 0) { - NotificationsManager.fromBackend("Please select at least one agent to make public"); + NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.selectAtLeastOne")); return; } @@ -94,12 +96,12 @@ const MakeAgentPublicForm: React.FC = ({ // Make batch API call for all agents await makeAgentsPublicCall(accessToken, agentIdsToMakePublic); - NotificationsManager.success(`Successfully made ${agentIdsToMakePublic.length} agent(s) public!`); + NotificationsManager.success(t("aiHub.makeAgentPublicForm.successCount", { count: agentIdsToMakePublic.length })); handleClose(); onSuccess(); } catch (error) { console.error("Error making agents public:", error); - NotificationsManager.fromBackend("Failed to make agents public. Please try again."); + NotificationsManager.fromBackend(t("aiHub.makeAgentPublicForm.failedToMakePublic")); } finally { setLoading(false); } @@ -113,7 +115,7 @@ const MakeAgentPublicForm: React.FC = ({ return (
- Select Agents to Make Public + {t("aiHub.makeAgentPublicForm.selectTitle")}
= ({ onChange={(e) => handleSelectAll(e.target.checked)} disabled={agentHubData.length === 0} > - Select All {agentHubData.length > 0 && `(${agentHubData.length})`} + {t("aiHub.makeAgentPublicForm.selectAll")} {agentHubData.length > 0 && `(${agentHubData.length})`}
- - Select the agents you want to be visible on the public model hub. Users will still require a valid Virtual Key - to use these agents. - + {t("aiHub.makeAgentPublicForm.selectDescription")}
{agentHubData.length === 0 ? (
- No agents available. + {t("aiHub.makeAgentPublicForm.noAgents")}
) : ( agentHubData.map((agent) => { @@ -162,7 +161,9 @@ const MakeAgentPublicForm: React.FC = ({ ))} {agent.skills.length > 3 && ( - +{agent.skills.length - 3} more + + {t("aiHub.makeAgentPublicForm.moreSkills", { count: agent.skills.length - 3 })} + )}
)} @@ -177,7 +178,7 @@ const MakeAgentPublicForm: React.FC = ({ {selectedAgents.size > 0 && (
- {selectedAgents.size} agent{selectedAgents.size !== 1 ? "s" : ""} selected + {t("aiHub.makeAgentPublicForm.selectedCount", { count: selectedAgents.size })}
)} @@ -188,17 +189,17 @@ const MakeAgentPublicForm: React.FC = ({ const renderStep2Content = () => { return (
- Confirm Making Agents Public + {t("aiHub.makeAgentPublicForm.confirmTitle")}
- Warning: Once you make these agents public, anyone who can go to the{" "} - /ui/model_hub_table will be able to know they exist on the proxy. + Warning:{" "} + }} />
- Agents to be made public: + {t("aiHub.makeAgentPublicForm.agentsToBeMadePublic")}
{Array.from(selectedAgents).map((agentId) => { @@ -225,8 +226,7 @@ const MakeAgentPublicForm: React.FC = ({
- Total: {selectedAgents.size} agent{selectedAgents.size !== 1 ? "s" : ""} will be made - public + {t("aiHub.makeAgentPublicForm.totalCount", { count: selectedAgents.size })}
@@ -248,19 +248,19 @@ const MakeAgentPublicForm: React.FC = ({ return (
{currentStep === 0 && ( )} {currentStep === 1 && ( )}
@@ -270,7 +270,7 @@ const MakeAgentPublicForm: React.FC = ({ return ( = ({ >
- - + + {renderStepContent()} diff --git a/ui/litellm-dashboard/src/components/AIHub/forms/MakeMCPPublicForm.tsx b/ui/litellm-dashboard/src/components/AIHub/forms/MakeMCPPublicForm.tsx index d7103da9ed7..53e03ed60f9 100644 --- a/ui/litellm-dashboard/src/components/AIHub/forms/MakeMCPPublicForm.tsx +++ b/ui/litellm-dashboard/src/components/AIHub/forms/MakeMCPPublicForm.tsx @@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react"; import { makeMCPPublicCall } from "../../networking"; import NotificationsManager from "../../molecules/notifications_manager"; import { MCPServerData } from "@/components/mcp_hub_table_columns"; +import { useTranslation, Trans } from "react-i18next"; const { Step } = Steps; @@ -22,6 +23,7 @@ const MakeMCPPublicForm: React.FC = ({ mcpHubData, onSuccess, }) => { + const { t } = useTranslation(); const [currentStep, setCurrentStep] = useState(0); const [selectedServers, setSelectedServers] = useState>(new Set()); const [loading, setLoading] = useState(false); @@ -37,7 +39,7 @@ const MakeMCPPublicForm: React.FC = ({ const handleNext = () => { if (currentStep === 0) { if (selectedServers.size === 0) { - NotificationsManager.fromBackend("Please select at least one MCP server to make public"); + NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.selectAtLeastOne")); return; } setCurrentStep(1); @@ -84,7 +86,7 @@ const MakeMCPPublicForm: React.FC = ({ const handleSubmit = async () => { if (selectedServers.size === 0) { - NotificationsManager.fromBackend("Please select at least one MCP server to make public"); + NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.selectAtLeastOne")); return; } @@ -95,12 +97,12 @@ const MakeMCPPublicForm: React.FC = ({ // Make batch API call for all servers await makeMCPPublicCall(accessToken, serverIdsToMakePublic); - NotificationsManager.success(`Successfully made ${serverIdsToMakePublic.length} MCP server(s) public!`); + NotificationsManager.success(t("aiHub.makeMCPPublicForm.successCount", { count: serverIdsToMakePublic.length })); handleClose(); onSuccess(); } catch (error) { console.error("Error making MCP servers public:", error); - NotificationsManager.fromBackend("Failed to make MCP servers public. Please try again."); + NotificationsManager.fromBackend(t("aiHub.makeMCPPublicForm.failedToMakePublic")); } finally { setLoading(false); } @@ -114,7 +116,7 @@ const MakeMCPPublicForm: React.FC = ({ return (
- Select MCP Servers to Make Public + {t("aiHub.makeMCPPublicForm.selectTitle")}
= ({ onChange={(e) => handleSelectAll(e.target.checked)} disabled={mcpHubData.length === 0} > - Select All {mcpHubData.length > 0 && `(${mcpHubData.length})`} + {t("aiHub.makeMCPPublicForm.selectAll")} {mcpHubData.length > 0 && `(${mcpHubData.length})`}
- - Select the MCP servers you want to be visible on the public model hub. Users will still require a valid - Virtual Key to use these servers. - + {t("aiHub.makeMCPPublicForm.selectDescription")}
{mcpHubData.length === 0 ? (
- No MCP servers available. + {t("aiHub.makeMCPPublicForm.noServers")}
) : ( mcpHubData.map((server) => { @@ -155,7 +154,7 @@ const MakeMCPPublicForm: React.FC = ({ {server.server_name} {isPublic && ( - Public + {t("aiHub.makeMCPPublicForm.badgePublic")} )} @@ -183,7 +182,9 @@ const MakeMCPPublicForm: React.FC = ({ ))} {server.allowed_tools.length > 3 && ( - +{server.allowed_tools.length - 3} more + + {t("aiHub.makeMCPPublicForm.moreTools", { count: server.allowed_tools.length - 3 })} + )}
)} @@ -198,7 +199,7 @@ const MakeMCPPublicForm: React.FC = ({ {selectedServers.size > 0 && (
- {selectedServers.size} MCP server{selectedServers.size !== 1 ? "s" : ""} selected + {t("aiHub.makeMCPPublicForm.selectedCount", { count: selectedServers.size })}
)} @@ -209,17 +210,17 @@ const MakeMCPPublicForm: React.FC = ({ const renderStep2Content = () => { return (
- Confirm Making MCP Servers Public + {t("aiHub.makeMCPPublicForm.confirmTitle")}
- Warning: Once you make these MCP servers public, anyone who can go to the{" "} - /ui/model_hub_table will be able to know they exist on the proxy. + Warning:{" "} + }} />
- MCP Servers to be made public: + {t("aiHub.makeMCPPublicForm.serversToBeMadePublic")}
{Array.from(selectedServers).map((serverId) => { @@ -261,8 +262,7 @@ const MakeMCPPublicForm: React.FC = ({
- Total: {selectedServers.size} MCP server{selectedServers.size !== 1 ? "s" : ""} will be - made public + {t("aiHub.makeMCPPublicForm.totalCount", { count: selectedServers.size })}
@@ -284,19 +284,19 @@ const MakeMCPPublicForm: React.FC = ({ return (
{currentStep === 0 && ( )} {currentStep === 1 && ( )}
@@ -306,7 +306,7 @@ const MakeMCPPublicForm: React.FC = ({ return ( = ({ > - - + + {renderStepContent()} diff --git a/ui/litellm-dashboard/src/components/AIHub/forms/MakeModelPublicForm.tsx b/ui/litellm-dashboard/src/components/AIHub/forms/MakeModelPublicForm.tsx index 16ed04c1779..501c0a01b8a 100644 --- a/ui/litellm-dashboard/src/components/AIHub/forms/MakeModelPublicForm.tsx +++ b/ui/litellm-dashboard/src/components/AIHub/forms/MakeModelPublicForm.tsx @@ -4,6 +4,7 @@ import { Text, Title, Badge } from "@tremor/react"; import { makeModelGroupPublic } from "../../networking"; import ModelFilters from "../../model_filters"; import NotificationsManager from "../../molecules/notifications_manager"; +import { useTranslation, Trans } from "react-i18next"; const { Step } = Steps; @@ -40,6 +41,7 @@ const MakeModelPublicForm: React.FC = ({ modelHubData, onSuccess, }) => { + const { t } = useTranslation(); const [currentStep, setCurrentStep] = useState(0); const [selectedModels, setSelectedModels] = useState>(new Set()); const [filteredData, setFilteredData] = useState([]); @@ -57,7 +59,7 @@ const MakeModelPublicForm: React.FC = ({ const handleNext = () => { if (currentStep === 0) { if (selectedModels.size === 0) { - NotificationsManager.fromBackend("Please select at least one model to make public"); + NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.selectAtLeastOne")); return; } setCurrentStep(1); @@ -110,7 +112,7 @@ const MakeModelPublicForm: React.FC = ({ const handleSubmit = async () => { if (selectedModels.size === 0) { - NotificationsManager.fromBackend("Please select at least one model to make public"); + NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.selectAtLeastOne")); return; } @@ -119,12 +121,14 @@ const MakeModelPublicForm: React.FC = ({ const modelGroupsToMakePublic = Array.from(selectedModels); await makeModelGroupPublic(accessToken, modelGroupsToMakePublic); - NotificationsManager.success(`Successfully made ${modelGroupsToMakePublic.length} model group(s) public!`); + NotificationsManager.success( + t("aiHub.makeModelPublicForm.successCount", { count: modelGroupsToMakePublic.length }), + ); handleClose(); onSuccess(); } catch (error) { console.error("Error making model groups public:", error); - NotificationsManager.fromBackend("Failed to make model groups public. Please try again."); + NotificationsManager.fromBackend(t("aiHub.makeModelPublicForm.failedToMakePublic")); } finally { setLoading(false); } @@ -138,7 +142,7 @@ const MakeModelPublicForm: React.FC = ({ return (
- Select Models to Make Public + {t("aiHub.makeModelPublicForm.selectTitle")}
= ({ onChange={(e) => handleSelectAll(e.target.checked)} disabled={filteredData.length === 0} > - Select All {filteredData.length > 0 && `(${filteredData.length})`} + {t("aiHub.makeModelPublicForm.selectAll")} {filteredData.length > 0 && `(${filteredData.length})`}
- - Select the models you want to be visible on the public model hub. Users will still require a valid Virtual Key - to use these models. - + {t("aiHub.makeModelPublicForm.selectDescription")} {/* Filters */} = ({
{filteredData.length === 0 ? (
- No models match the current filters. + {t("aiHub.makeModelPublicForm.noModels")}
) : ( filteredData.map((model) => ( @@ -206,7 +207,7 @@ const MakeModelPublicForm: React.FC = ({ {selectedModels.size > 0 && (
- {selectedModels.size} model{selectedModels.size !== 1 ? "s" : ""} selected + {t("aiHub.makeModelPublicForm.selectedCount", { count: selectedModels.size })}
)} @@ -217,17 +218,17 @@ const MakeModelPublicForm: React.FC = ({ const renderStep2Content = () => { return (
- Confirm Making Models Public + {t("aiHub.makeModelPublicForm.confirmTitle")}
- Warning: Once you make these models public, anyone who can go to the{" "} - /ui/model_hub_table will be able to know they exist on the proxy. + Warning:{" "} + }} />
- Models to be made public: + {t("aiHub.makeModelPublicForm.modelsToBeMadePublic")}
{Array.from(selectedModels).map((modelGroup) => { @@ -255,8 +256,7 @@ const MakeModelPublicForm: React.FC = ({
- Total: {selectedModels.size} model{selectedModels.size !== 1 ? "s" : ""} will be made - public + {t("aiHub.makeModelPublicForm.totalCount", { count: selectedModels.size })}
@@ -278,19 +278,19 @@ const MakeModelPublicForm: React.FC = ({ return (
{currentStep === 0 && ( )} {currentStep === 1 && ( )}
@@ -300,7 +300,7 @@ const MakeModelPublicForm: React.FC = ({ return ( = ({ > - - + + {renderStepContent()} diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index efac8f6e345..60b174899b0 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -6593,6 +6593,102 @@ "searchPlaceholder": "Search by name, namespace, or tag…", "showing_one": "Showing {{filtered}} of {{count}} skill", "showing_other": "Showing {{filtered}} of {{count}} skills" + }, + "usefulLinksManagement": { + "title": "Link Management", + "description": "Manage the links that are displayed under 'Useful Links' on the public model hub.", + "addNewLink": "Add New Link", + "labelDisplayName": "Display Name", + "placeholderDisplayName": "Friendly name", + "addLink": "Add Link", + "manageExistingLinks": "Manage Existing Links", + "publicModelHub": "Public Model Hub", + "openPublicModelHub": "Open Public Model Hub", + "rearrangeOrder": "Rearrange Order", + "saveOrder": "Save Order", + "colDisplayName": "Display Name", + "colActions": "Actions", + "tooltipMoveUp": "Move up", + "tooltipAlreadyAtTop": "Already at the top", + "tooltipMoveDown": "Move down", + "tooltipAlreadyAtBottom": "Already at the bottom", + "tooltipOpenLink": "Open link", + "tooltipEditLink": "Edit link", + "tooltipDeleteLink": "Delete link", + "noLinks": "No links added yet. Add a new link above.", + "saveLinksFailed": "Failed to save links - {{error}}", + "invalidUrl": "Please enter a valid URL", + "duplicateDisplayName": "A link with this display name already exists", + "addSuccess": "Link added successfully", + "updateSuccess": "Link updated successfully", + "deleteSuccess": "Link deleted successfully", + "reorderSuccess": "Link order saved successfully" + }, + "makeAgentPublicForm": { + "modalTitle": "Make Agents Public", + "stepSelectAgents": "Select Agents", + "stepConfirm": "Confirm", + "selectTitle": "Select Agents to Make Public", + "selectAll": "Select All", + "selectDescription": "Select the agents you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these agents.", + "noAgents": "No agents available.", + "moreSkills": "+{{count}} more", + "selectedCount_one": "{{count}} agent selected", + "selectedCount_other": "{{count}} agents selected", + "confirmTitle": "Confirm Making Agents Public", + "warningText": "Once you make these agents public, anyone who can go to the /ui/model_hub_table will be able to know they exist on the proxy.", + "agentsToBeMadePublic": "Agents to be made public:", + "totalCount_one": "Total: {{count}} agent will be made public", + "totalCount_other": "Total: {{count}} agents will be made public", + "makePublic": "Make Public", + "selectAtLeastOne": "Please select at least one agent to make public", + "successCount_one": "Successfully made {{count}} agent public!", + "successCount_other": "Successfully made {{count}} agents public!", + "failedToMakePublic": "Failed to make agents public. Please try again." + }, + "makeMCPPublicForm": { + "modalTitle": "Make MCP Servers Public", + "stepSelectServers": "Select Servers", + "stepConfirm": "Confirm", + "selectTitle": "Select MCP Servers to Make Public", + "selectAll": "Select All", + "selectDescription": "Select the MCP servers you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these servers.", + "noServers": "No MCP servers available.", + "moreTools": "+{{count}} more", + "selectedCount_one": "{{count}} MCP server selected", + "selectedCount_other": "{{count}} MCP servers selected", + "confirmTitle": "Confirm Making MCP Servers Public", + "warningText": "Once you make these MCP servers public, anyone who can go to the /ui/model_hub_table will be able to know they exist on the proxy.", + "serversToBeMadePublic": "MCP Servers to be made public:", + "totalCount_one": "Total: {{count}} MCP server will be made public", + "totalCount_other": "Total: {{count}} MCP servers will be made public", + "makePublic": "Make Public", + "badgePublic": "Public", + "selectAtLeastOne": "Please select at least one MCP server to make public", + "successCount_one": "Successfully made {{count}} MCP server public!", + "successCount_other": "Successfully made {{count}} MCP servers public!", + "failedToMakePublic": "Failed to make MCP servers public. Please try again." + }, + "makeModelPublicForm": { + "modalTitle": "Make Models Public", + "stepSelectModels": "Select Models", + "stepConfirm": "Confirm", + "selectTitle": "Select Models to Make Public", + "selectAll": "Select All", + "selectDescription": "Select the models you want to be visible on the public model hub. Users will still require a valid Virtual Key to use these models.", + "noModels": "No models match the current filters.", + "selectedCount_one": "{{count}} model selected", + "selectedCount_other": "{{count}} models selected", + "confirmTitle": "Confirm Making Models Public", + "warningText": "Once you make these models public, anyone who can go to the /ui/model_hub_table will be able to know they exist on the proxy.", + "modelsToBeMadePublic": "Models to be made public:", + "totalCount_one": "Total: {{count}} model will be made public", + "totalCount_other": "Total: {{count}} models will be made public", + "makePublic": "Make Public", + "selectAtLeastOne": "Please select at least one model to make public", + "successCount_one": "Successfully made {{count}} model group public!", + "successCount_other": "Successfully made {{count}} model groups public!", + "failedToMakePublic": "Failed to make model groups public. Please try again." } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index 14bb46fd12f..61212793300 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -6593,6 +6593,102 @@ "searchPlaceholder": "按名称、命名空间或标签搜索…", "showing_one": "显示 {{filtered}} / {{count}} 个技能", "showing_other": "显示 {{filtered}} / {{count}} 个技能" + }, + "usefulLinksManagement": { + "title": "链接管理", + "description": "管理公开模型 Hub 上「实用链接」栏目中显示的链接。", + "addNewLink": "添加新链接", + "labelDisplayName": "显示名称", + "placeholderDisplayName": "友好名称", + "addLink": "添加链接", + "manageExistingLinks": "管理现有链接", + "publicModelHub": "公开模型 Hub", + "openPublicModelHub": "打开公开模型 Hub", + "rearrangeOrder": "重新排序", + "saveOrder": "保存顺序", + "colDisplayName": "显示名称", + "colActions": "操作", + "tooltipMoveUp": "上移", + "tooltipAlreadyAtTop": "已在顶部", + "tooltipMoveDown": "下移", + "tooltipAlreadyAtBottom": "已在底部", + "tooltipOpenLink": "打开链接", + "tooltipEditLink": "编辑链接", + "tooltipDeleteLink": "删除链接", + "noLinks": "暂无链接,请在上方添加新链接。", + "saveLinksFailed": "保存链接失败 - {{error}}", + "invalidUrl": "请输入有效的 URL", + "duplicateDisplayName": "已存在同名显示名称的链接", + "addSuccess": "链接添加成功", + "updateSuccess": "链接更新成功", + "deleteSuccess": "链接删除成功", + "reorderSuccess": "链接顺序保存成功" + }, + "makeAgentPublicForm": { + "modalTitle": "将 Agent 设为公开", + "stepSelectAgents": "选择 Agent", + "stepConfirm": "确认", + "selectTitle": "选择要公开的 Agent", + "selectAll": "全选", + "selectDescription": "选择要在公开模型 Hub 上展示的 Agent。用户仍需有效的虚拟密钥才能使用这些 Agent。", + "noAgents": "暂无可用 Agent。", + "moreSkills": "+{{count}} 个", + "selectedCount_one": "已选择 {{count}} 个 Agent", + "selectedCount_other": "已选择 {{count}} 个 Agent", + "confirmTitle": "确认将 Agent 设为公开", + "warningText": "将这些 Agent 设为公开后,任何能访问 /ui/model_hub_table 的用户都能知道它们存在于代理中。", + "agentsToBeMadePublic": "即将设为公开的 Agent:", + "totalCount_one": "共 {{count}} 个 Agent 将被设为公开", + "totalCount_other": "共 {{count}} 个 Agent 将被设为公开", + "makePublic": "设为公开", + "selectAtLeastOne": "请至少选择一个 Agent 以设为公开", + "successCount_one": "成功将 {{count}} 个 Agent 设为公开!", + "successCount_other": "成功将 {{count}} 个 Agent 设为公开!", + "failedToMakePublic": "将 Agent 设为公开失败,请重试。" + }, + "makeMCPPublicForm": { + "modalTitle": "将 MCP 服务器设为公开", + "stepSelectServers": "选择服务器", + "stepConfirm": "确认", + "selectTitle": "选择要公开的 MCP 服务器", + "selectAll": "全选", + "selectDescription": "选择要在公开模型 Hub 上展示的 MCP 服务器。用户仍需有效的虚拟密钥才能使用这些服务器。", + "noServers": "暂无可用 MCP 服务器。", + "moreTools": "+{{count}} 个", + "selectedCount_one": "已选择 {{count}} 个 MCP 服务器", + "selectedCount_other": "已选择 {{count}} 个 MCP 服务器", + "confirmTitle": "确认将 MCP 服务器设为公开", + "warningText": "将这些 MCP 服务器设为公开后,任何能访问 /ui/model_hub_table 的用户都能知道它们存在于代理中。", + "serversToBeMadePublic": "即将设为公开的 MCP 服务器:", + "totalCount_one": "共 {{count}} 个 MCP 服务器将被设为公开", + "totalCount_other": "共 {{count}} 个 MCP 服务器将被设为公开", + "makePublic": "设为公开", + "badgePublic": "公开", + "selectAtLeastOne": "请至少选择一个 MCP 服务器以设为公开", + "successCount_one": "成功将 {{count}} 个 MCP 服务器设为公开!", + "successCount_other": "成功将 {{count}} 个 MCP 服务器设为公开!", + "failedToMakePublic": "将 MCP 服务器设为公开失败,请重试。" + }, + "makeModelPublicForm": { + "modalTitle": "将模型设为公开", + "stepSelectModels": "选择模型", + "stepConfirm": "确认", + "selectTitle": "选择要公开的模型", + "selectAll": "全选", + "selectDescription": "选择要在公开模型 Hub 上展示的模型。用户仍需有效的虚拟密钥才能使用这些模型。", + "noModels": "没有与当前筛选条件匹配的模型。", + "selectedCount_one": "已选择 {{count}} 个模型", + "selectedCount_other": "已选择 {{count}} 个模型", + "confirmTitle": "确认将模型设为公开", + "warningText": "将这些模型设为公开后,任何能访问 /ui/model_hub_table 的用户都能知道它们存在于代理中。", + "modelsToBeMadePublic": "即将设为公开的模型:", + "totalCount_one": "共 {{count}} 个模型将被设为公开", + "totalCount_other": "共 {{count}} 个模型将被设为公开", + "makePublic": "设为公开", + "selectAtLeastOne": "请至少选择一个模型以设为公开", + "successCount_one": "成功将 {{count}} 个模型组设为公开!", + "successCount_other": "成功将 {{count}} 个模型组设为公开!", + "failedToMakePublic": "将模型组设为公开失败,请重试。" } } }