diff --git a/ui/litellm-dashboard/src/components/object_permissions_view.tsx b/ui/litellm-dashboard/src/components/object_permissions_view.tsx index be021a5b59d..d7a29afd4d8 100644 --- a/ui/litellm-dashboard/src/components/object_permissions_view.tsx +++ b/ui/litellm-dashboard/src/components/object_permissions_view.tsx @@ -1,5 +1,6 @@ import React from "react"; import { Text } from "@tremor/react"; +import { useTranslation } from "react-i18next"; import VectorStorePermissions from "./permissions/VectorStorePermissions"; import MCPServerPermissions from "./permissions/MCPServerPermissions"; import AgentPermissions from "./permissions/AgentPermissions"; @@ -29,6 +30,7 @@ export function ObjectPermissionsView({ className = "", accessToken, }: ObjectPermissionsViewProps) { + const { t } = useTranslation(); const vectorStores = objectPermission?.vector_stores || []; const mcpServers = objectPermission?.mcp_servers || []; const mcpAccessGroups = objectPermission?.mcp_access_groups || []; @@ -50,10 +52,10 @@ export function ObjectPermissionsView({ />
- Search tools + {t("objectPermissionsView.searchToolsTitle")} {searchTools.length === 0 ? ( - No restriction — all configured search tools are allowed for this team. + {t("objectPermissionsView.searchToolsNoRestriction")} ) : ( {searchTools.join(", ")} @@ -67,8 +69,8 @@ export function ObjectPermissionsView({
- Object Permissions - Access control for Vector Stores and MCP Servers + {t("objectPermissionsView.title")} + {t("objectPermissionsView.subtitle")}
{content} @@ -78,7 +80,7 @@ export function ObjectPermissionsView({ return (
- Object Permissions + {t("objectPermissionsView.title")} {content}
); diff --git a/ui/litellm-dashboard/src/components/onboarding_link.tsx b/ui/litellm-dashboard/src/components/onboarding_link.tsx index 7eb337a970a..f0eb1e3e344 100644 --- a/ui/litellm-dashboard/src/components/onboarding_link.tsx +++ b/ui/litellm-dashboard/src/components/onboarding_link.tsx @@ -2,6 +2,7 @@ import React from "react"; import { Button, Modal, Typography } from "antd"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { Text } from "@tremor/react"; +import { useTranslation } from "react-i18next"; import NotificationsManager from "./molecules/notifications_manager"; export interface InvitationLink { @@ -32,6 +33,7 @@ export default function OnboardingModal({ invitationLinkData, modalType = "invitation", }: OnboardingProps) { + const { t } = useTranslation(); const { Title, Paragraph } = Typography; const handleInvitationOk = () => { setIsInvitationLinkModalVisible(false); @@ -62,7 +64,11 @@ export default function OnboardingModal({ return ( {modalType === "invitation" - ? "Copy and send the generated link to onboard this user to the proxy." - : "Copy and send the generated link to the user to reset their password."} + ? t("onboardingLink.invitationLinkDesc") + : t("onboardingLink.resetPasswordLinkDesc")}
- User ID + {t("onboardingLink.userId")} {invitationLinkData?.user_id}
- {modalType === "invitation" ? "Invitation Link" : "Reset Password Link"} + + {modalType === "invitation" + ? t("onboardingLink.invitationLinkTitle") + : t("onboardingLink.resetPasswordLinkTitle")} + {getInvitationUrl()}
- NotificationsManager.success("Copied!")}> + NotificationsManager.success(t("common.copied"))}>
diff --git a/ui/litellm-dashboard/src/components/organizations.tsx b/ui/litellm-dashboard/src/components/organizations.tsx index fc825bdf924..aaeff0d0da9 100644 --- a/ui/litellm-dashboard/src/components/organizations.tsx +++ b/ui/litellm-dashboard/src/components/organizations.tsx @@ -1,5 +1,6 @@ import OrganizationFilters, { FilterState } from "@/app/(dashboard)/organizations/OrganizationFilters"; import { InfoCircleOutlined } from "@ant-design/icons"; +import { Trans, useTranslation } from "react-i18next"; import { ChevronDownIcon, ChevronRightIcon, RefreshIcon } from "@heroicons/react/outline"; import { Badge, @@ -71,6 +72,7 @@ const OrganizationsTable: React.FC = ({ setOrganizations, premiumUser, }) => { + const { t } = useTranslation(); const [selectedOrgId, setSelectedOrgId] = useState(null); const [editOrg, setEditOrg] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); @@ -138,7 +140,7 @@ const OrganizationsTable: React.FC = ({ try { setIsDeleting(true); await organizationDeleteCall(accessToken, orgToDelete); - NotificationsManager.success("Organization deleted successfully"); + NotificationsManager.success(t("organizations.deleteSuccess")); setIsDeleteModalOpen(false); setOrgToDelete(null); @@ -186,7 +188,7 @@ const OrganizationsTable: React.FC = ({ } await organizationCreateCall(accessToken, values); - NotificationsManager.success("Organization created successfully"); + NotificationsManager.success(t("organizations.createSuccess")); setIsOrgModalVisible(false); form.resetFields(); // Refresh organizations list @@ -205,11 +207,12 @@ const OrganizationsTable: React.FC = ({ return (
- This is a LiteLLM Enterprise feature, and requires a valid key to use. Get a trial key{" "} - - here - - . + , + }} + />
); @@ -221,7 +224,7 @@ const OrganizationsTable: React.FC = ({ {(userRole === "Admin" || userRole === "Org Admin") && ( )} {selectedOrgId ? ( @@ -241,10 +244,10 @@ const OrganizationsTable: React.FC = ({
- Your Organizations + {t("organizations.tabYourOrgs")}
- {lastRefreshed && Last Refreshed: {lastRefreshed}} + {lastRefreshed && {t("organizations.lastRefreshed", { time: lastRefreshed })}} = ({ - Click on “Organization ID” to view organization details. + {t("organizations.clickOrgIdHint")} @@ -274,15 +277,15 @@ const OrganizationsTable: React.FC = ({ - Organization ID - Organization Name - Created - Spend (USD) - Budget (USD) - Models - TPM / RPM Limits - Info - Actions + {t("organizations.colOrgId")} + {t("organizations.colOrgName")} + {t("common.createdAt")} + {t("organizations.colSpend")} + {t("organizations.colBudget")} + {t("organizations.colModels")} + {t("organizations.colTpmRpmLimits")} + {t("organizations.colInfo")} + {t("common.actions")} @@ -309,14 +312,16 @@ const OrganizationsTable: React.FC = ({ {org.organization_alias} - {org.created_at ? new Date(org.created_at).toLocaleDateString() : "N/A"} + {org.created_at + ? new Date(org.created_at).toLocaleDateString() + : t("organizations.notAvailable")} {formatNumberWithCommas(org.spend, 4)} {org.litellm_budget_table?.max_budget !== null && org.litellm_budget_table?.max_budget !== undefined ? org.litellm_budget_table?.max_budget - : "No limit"} + : t("organizations.noLimit")} = ({
{org.models.length === 0 ? ( - All Proxy Models + {t("organizations.allProxyModels")} ) : ( <> @@ -360,7 +365,7 @@ const OrganizationsTable: React.FC = ({ {org.models.slice(0, 3).map((model, index) => model === "all-proxy-models" ? ( - All Proxy Models + {t("organizations.allProxyModels")} ) : ( @@ -376,10 +381,9 @@ const OrganizationsTable: React.FC = ({ !expandedAccordions[org.organization_id || ""] && ( - +{org.models.length - 3}{" "} - {org.models.length - 3 === 1 - ? "more model" - : "more models"} + {t("organizations.moreModels", { + count: org.models.length - 3, + })} )} @@ -388,7 +392,7 @@ const OrganizationsTable: React.FC = ({ {org.models.slice(3).map((model, index) => model === "all-proxy-models" ? ( - All Proxy Models + {t("organizations.allProxyModels")} ) : ( @@ -412,26 +416,28 @@ const OrganizationsTable: React.FC = ({ - TPM:{" "} + {t("organizations.tpmLabel")}:{" "} {org.litellm_budget_table?.tpm_limit ? org.litellm_budget_table?.tpm_limit - : "Unlimited"} + : t("organizations.unlimited")}
- RPM:{" "} + {t("organizations.rpmLabel")}:{" "} {org.litellm_budget_table?.rpm_limit ? org.litellm_budget_table?.rpm_limit - : "Unlimited"} + : t("organizations.unlimited")}
- {org.members?.length || 0} Members + + {t("organizations.memberCount", { count: org.members?.length || 0 })} + {userRole === "Admin" && ( <> { setSelectedOrgId(org.organization_id); setEditOrg(true); @@ -439,7 +445,7 @@ const OrganizationsTable: React.FC = ({ /> handleDelete(org.organization_id)} /> @@ -459,21 +465,27 @@ const OrganizationsTable: React.FC = ({ )} - +
- + = ({ /> - + - + - daily - weekly - monthly + {t("commonComponents.durationSelect.daily")} + {t("commonComponents.durationSelect.weekly")} + {t("commonComponents.durationSelect.monthly")} - + - + - Allowed Vector Stores{" "} - + {t("organizations.formAllowedVectorStores")}{" "} + } name="allowed_vector_store_ids" className="mt-4" - help="Select vector stores this organization can access. Leave empty for access to all vector stores" + help={t("organizations.formAllowedVectorStoresHelp")} > form.setFieldValue("allowed_vector_store_ids", values)} value={form.getFieldValue("allowed_vector_store_ids")} accessToken={accessToken || ""} - placeholder="Select vector stores (optional)" + placeholder={t("organizations.formAllowedVectorStoresPlaceholder")} /> - Allowed MCP Servers{" "} - + {t("organizations.formAllowedMcpServers")}{" "} + } name="allowed_mcp_servers_and_groups" className="mt-4" - help="Select MCP servers and access groups this organization can access." + help={t("organizations.formAllowedMcpServersHelp")} > form.setFieldValue("allowed_mcp_servers_and_groups", values)} value={form.getFieldValue("allowed_mcp_servers_and_groups")} accessToken={accessToken || ""} - placeholder="Select MCP servers and access groups (optional)" + placeholder={t("organizations.formAllowedMcpServersPlaceholder")} /> - +
- +
= ({ premiumUser = false, onEndpointUpdated, }) => { + const { t } = useTranslation(); const [endpointData, setEndpointData] = useState(initialEndpointData); const [loading, setLoading] = useState(false); const [isEditing, setIsEditing] = useState(false); @@ -90,7 +92,7 @@ const PassThroughInfoView: React.FC = ({ try { headers = typeof values.headers === "string" ? JSON.parse(values.headers) : values.headers; } catch (e) { - NotificationsManager.fromBackend("Invalid JSON format for headers"); + NotificationsManager.fromBackend(t("passThroughInfo.invalidJsonHeaders")); return; } } @@ -120,7 +122,7 @@ const PassThroughInfoView: React.FC = ({ } } catch (error) { console.error("Error updating endpoint:", error); - NotificationsManager.fromBackend("Failed to update pass through endpoint"); + NotificationsManager.fromBackend(t("passThroughInfo.updateFailed")); } }; @@ -129,23 +131,23 @@ const PassThroughInfoView: React.FC = ({ if (!accessToken || !endpointData?.id) return; await deletePassThroughEndpointsCall(accessToken, endpointData.id); - NotificationsManager.success("Pass through endpoint deleted successfully"); + NotificationsManager.success(t("passThroughInfo.deleteSuccess")); onClose(); if (onEndpointUpdated) { onEndpointUpdated(); } } catch (error) { console.error("Error deleting endpoint:", error); - NotificationsManager.fromBackend("Failed to delete pass through endpoint"); + NotificationsManager.fromBackend(t("passThroughInfo.deleteFailed")); } }; if (loading) { - return
Loading...
; + return
{t("common.loading")}
; } if (!endpointData) { - return
Pass through endpoint not found
; + return
{t("passThroughInfo.notFound")}
; } return ( @@ -153,17 +155,17 @@ const PassThroughInfoView: React.FC = ({
- Pass Through Endpoint: {endpointData.path} + {t("passThroughInfo.pageTitle", { path: endpointData.path })} {endpointData.id}
- Overview - {isAdmin ? Settings : <>} + {t("passThroughInfo.tabOverview")} + {isAdmin ? {t("common.settings")} : <>} @@ -171,35 +173,37 @@ const PassThroughInfoView: React.FC = ({ - Path + {t("passThroughInfo.labelPath")}
{endpointData.path}
- Target + {t("passThroughInfo.labelTarget")}
{endpointData.target}
- Configuration + {t("passThroughInfo.labelConfiguration")}
- {endpointData.include_subpath ? "Include Subpath" : "Exact Path"} + {endpointData.include_subpath + ? t("passThroughInfo.includeSubpath") + : t("passThroughInfo.exactPath")}
- {endpointData.auth ? "Auth Required" : "No Auth"} + {endpointData.auth ? t("passThroughInfo.authRequired") : t("passThroughInfo.noAuth")}
{endpointData.methods && endpointData.methods.length > 0 && (
- HTTP Methods: + {t("passThroughInfo.httpMethods")}
{endpointData.methods.map((method) => ( @@ -211,12 +215,12 @@ const PassThroughInfoView: React.FC = ({ )} {(!endpointData.methods || endpointData.methods.length === 0) && (
- All HTTP methods supported + {t("passThroughInfo.allHttpMethodsSupported")}
)} {endpointData.cost_per_request !== undefined && (
- Cost per request: ${endpointData.cost_per_request} + {t("passThroughInfo.costPerRequest", { cost: endpointData.cost_per_request })}
)}
@@ -235,8 +239,10 @@ const PassThroughInfoView: React.FC = ({ {endpointData.headers && Object.keys(endpointData.headers).length > 0 && (
- Headers - {Object.keys(endpointData.headers).length} headers configured + {t("passThroughInfo.labelHeaders")} + + {t("passThroughInfo.headersConfigured", { count: Object.keys(endpointData.headers).length })} +
@@ -247,8 +253,10 @@ const PassThroughInfoView: React.FC = ({ {endpointData.guardrails && Object.keys(endpointData.guardrails).length > 0 && (
- Guardrails - {Object.keys(endpointData.guardrails).length} guardrails configured + {t("passThroughInfo.labelGuardrails")} + + {t("passThroughInfo.guardrailsConfigured", { count: Object.keys(endpointData.guardrails).length })} +
{Object.entries(endpointData.guardrails).map(([name, settings]) => ( @@ -256,13 +264,21 @@ const PassThroughInfoView: React.FC = ({
{name}
{settings && (settings.request_fields || settings.response_fields) && (
- {settings.request_fields &&
Request fields: {settings.request_fields.join(", ")}
} + {settings.request_fields && ( +
+ {t("passThroughInfo.requestFields", { fields: settings.request_fields.join(", ") })} +
+ )} {settings.response_fields && ( -
Response fields: {settings.response_fields.join(", ")}
+
+ {t("passThroughInfo.responseFields", { fields: settings.response_fields.join(", ") })} +
)}
)} - {!settings &&
Uses entire payload
} + {!settings && ( +
{t("passThroughInfo.usesEntirePayload")}
+ )}
))}
@@ -275,13 +291,15 @@ const PassThroughInfoView: React.FC = ({
- Pass Through Endpoint Settings + {t("passThroughInfo.settingsTitle")}
{!isEditing && ( <> - setIsEditing(true)}>Edit Settings + setIsEditing(true)}> + {t("passThroughInfo.editSettings")} + - Delete Endpoint + {t("passThroughInfo.deleteEndpoint")} )} @@ -303,14 +321,14 @@ const PassThroughInfoView: React.FC = ({ layout="vertical" > - + = ({ - + - + @@ -368,44 +390,46 @@ const PassThroughInfoView: React.FC = ({
- - Save Changes + + {t("passThroughInfo.saveChanges")}
) : (
- Path + {t("passThroughInfo.labelPath")}
{endpointData.path}
- Target URL + {t("passThroughInfo.formTargetUrl")}
{endpointData.target}
- Include Subpath + {t("passThroughInfo.formIncludeSubpath")} - {endpointData.include_subpath ? "Yes" : "No"} + {endpointData.include_subpath ? t("common.yes") : t("common.no")}
{endpointData.cost_per_request !== undefined && (
- Cost per Request + {t("passThroughInfo.formCostPerRequest")}
${endpointData.cost_per_request}
)}
- Authentication Required - {endpointData.auth ? "Yes" : "No"} + {t("passThroughInfo.authenticationRequired")} + + {endpointData.auth ? t("common.yes") : t("common.no")} +
- Headers + {t("passThroughInfo.labelHeaders")} {endpointData.headers && Object.keys(endpointData.headers).length > 0 ? (
) : ( -
No headers configured
+
{t("passThroughInfo.noHeadersConfigured")}
)}
diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index 0095e87a1d7..a75dd93f461 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -1466,5 +1466,112 @@ "createdAt": "Created At", "updatedAt": "Updated At", "comingSoon": "Coming soon" + }, + "objectPermissionsView": { + "title": "Object Permissions", + "subtitle": "Access control for Vector Stores and MCP Servers", + "searchToolsTitle": "Search tools", + "searchToolsNoRestriction": "No restriction — all configured search tools are allowed for this team." + }, + "onboardingLink": { + "invitationLinkTitle": "Invitation Link", + "resetPasswordLinkTitle": "Reset Password Link", + "invitationLinkDesc": "Copy and send the generated link to onboard this user to the proxy.", + "resetPasswordLinkDesc": "Copy and send the generated link to the user to reset their password.", + "userId": "User ID", + "copyInvitationLink": "Copy invitation link", + "copyPasswordResetLink": "Copy password reset link" + }, + "organizations": { + "enterpriseFeature": "This is a LiteLLM Enterprise feature, and requires a valid key to use. Get a trial key here.", + "createNewOrg": "+ Create New Organization", + "tabYourOrgs": "Your Organizations", + "lastRefreshed": "Last Refreshed: {{time}}", + "clickOrgIdHint": "Click on \"Organization ID\" to view organization details.", + "colOrgId": "Organization ID", + "colOrgName": "Organization Name", + "colSpend": "Spend (USD)", + "colBudget": "Budget (USD)", + "colModels": "Models", + "colTpmRpmLimits": "TPM / RPM Limits", + "colInfo": "Info", + "notAvailable": "N/A", + "noLimit": "No limit", + "allProxyModels": "All Proxy Models", + "moreModels_one": "+{{count}} more model", + "moreModels_other": "+{{count}} more models", + "tpmLabel": "TPM", + "rpmLabel": "RPM", + "unlimited": "Unlimited", + "memberCount_one": "{{count}} Member", + "memberCount_other": "{{count}} Members", + "editOrgTooltip": "Edit organization", + "deleteOrgTooltip": "Delete organization", + "createModalTitle": "Create Organization", + "formOrgName": "Organization Name", + "formOrgNameRequired": "Please input an organization name", + "formModels": "Models", + "formMaxBudget": "Max Budget (USD)", + "formResetBudget": "Reset Budget", + "formTpmLimit": "Tokens per minute Limit (TPM)", + "formRpmLimit": "Requests per minute Limit (RPM)", + "formAllowedVectorStores": "Allowed Vector Stores", + "formAllowedVectorStoresTooltip": "Select which vector stores this organization can access by default. Leave empty for access to all vector stores", + "formAllowedVectorStoresHelp": "Select vector stores this organization can access. Leave empty for access to all vector stores", + "formAllowedVectorStoresPlaceholder": "Select vector stores (optional)", + "formAllowedMcpServers": "Allowed MCP Servers", + "formAllowedMcpServersTooltip": "Select which MCP servers and access groups this organization can access by default.", + "formAllowedMcpServersHelp": "Select MCP servers and access groups this organization can access.", + "formAllowedMcpServersPlaceholder": "Select MCP servers and access groups (optional)", + "formMetadata": "Metadata", + "deleteModalTitle": "Delete Organization?", + "deleteModalMessage": "Are you sure you want to delete this organization? This action cannot be undone.", + "deleteModalResourceTitle": "Organization Information", + "deleteSuccess": "Organization deleted successfully", + "createSuccess": "Organization created successfully" + }, + "passThroughInfo": { + "notFound": "Pass through endpoint not found", + "backButton": "← Back", + "pageTitle": "Pass Through Endpoint: {{path}}", + "tabOverview": "Overview", + "labelPath": "Path", + "labelTarget": "Target", + "labelConfiguration": "Configuration", + "includeSubpath": "Include Subpath", + "exactPath": "Exact Path", + "authRequired": "Auth Required", + "noAuth": "No Auth", + "httpMethods": "HTTP Methods:", + "allHttpMethodsSupported": "All HTTP methods supported", + "costPerRequest": "Cost per request: ${{cost}}", + "labelHeaders": "Headers", + "headersConfigured_one": "{{count}} header configured", + "headersConfigured_other": "{{count}} headers configured", + "labelGuardrails": "Guardrails", + "guardrailsConfigured_one": "{{count}} guardrail configured", + "guardrailsConfigured_other": "{{count}} guardrails configured", + "requestFields": "Request fields: {{fields}}", + "responseFields": "Response fields: {{fields}}", + "usesEntirePayload": "Uses entire payload", + "settingsTitle": "Pass Through Endpoint Settings", + "editSettings": "Edit Settings", + "deleteEndpoint": "Delete Endpoint", + "formTargetUrl": "Target URL", + "formTargetUrlRequired": "Please input a target URL", + "formHeadersJson": "Headers (JSON)", + "formHttpMethods": "HTTP Methods (Optional)", + "allHttpMethodsDefault": "All HTTP methods supported (default)", + "selectedMethodsDesc": "Only {{methods}} requests will be routed to this endpoint", + "selectMethodsPlaceholder": "Select methods (leave empty for all)", + "formIncludeSubpath": "Include Subpath", + "formCostPerRequest": "Cost per Request", + "saveChanges": "Save Changes", + "authenticationRequired": "Authentication Required", + "noHeadersConfigured": "No headers configured", + "invalidJsonHeaders": "Invalid JSON format for headers", + "updateFailed": "Failed to update pass through endpoint", + "deleteSuccess": "Pass through endpoint deleted successfully", + "deleteFailed": "Failed to delete pass through endpoint" } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index cbfe08966ca..5a7b6e35adf 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -1466,5 +1466,112 @@ "createdAt": "创建时间", "updatedAt": "更新时间", "comingSoon": "即将推出" + }, + "objectPermissionsView": { + "title": "对象权限", + "subtitle": "向量存储与 MCP 服务器的访问控制", + "searchToolsTitle": "搜索工具", + "searchToolsNoRestriction": "无限制 — 该团队可使用所有已配置的搜索工具。" + }, + "onboardingLink": { + "invitationLinkTitle": "邀请链接", + "resetPasswordLinkTitle": "重置密码链接", + "invitationLinkDesc": "复制并将生成的链接发送给该用户,以便将其接入代理。", + "resetPasswordLinkDesc": "复制并将生成的链接发送给该用户,以便其重置密码。", + "userId": "用户 ID", + "copyInvitationLink": "复制邀请链接", + "copyPasswordResetLink": "复制密码重置链接" + }, + "organizations": { + "enterpriseFeature": "这是 LiteLLM 企业版功能,需要有效的密钥才能使用。获取试用密钥请访问此处。", + "createNewOrg": "+ 创建新组织", + "tabYourOrgs": "我的组织", + "lastRefreshed": "最后刷新:{{time}}", + "clickOrgIdHint": "点击「组织 ID」可查看组织详情。", + "colOrgId": "组织 ID", + "colOrgName": "组织名称", + "colSpend": "花费(USD)", + "colBudget": "预算(USD)", + "colModels": "模型", + "colTpmRpmLimits": "TPM / RPM 限制", + "colInfo": "信息", + "notAvailable": "N/A", + "noLimit": "无限制", + "allProxyModels": "所有代理模型", + "moreModels_one": "+{{count}} 个模型", + "moreModels_other": "+{{count}} 个模型", + "tpmLabel": "TPM", + "rpmLabel": "RPM", + "unlimited": "无限制", + "memberCount_one": "{{count}} 位成员", + "memberCount_other": "{{count}} 位成员", + "editOrgTooltip": "编辑组织", + "deleteOrgTooltip": "删除组织", + "createModalTitle": "创建组织", + "formOrgName": "组织名称", + "formOrgNameRequired": "请输入组织名称", + "formModels": "模型", + "formMaxBudget": "最大预算(USD)", + "formResetBudget": "重置预算", + "formTpmLimit": "每分钟 Token 限制(TPM)", + "formRpmLimit": "每分钟请求限制(RPM)", + "formAllowedVectorStores": "允许的向量存储", + "formAllowedVectorStoresTooltip": "选择此组织默认可访问的向量存储。留空则允许访问所有向量存储", + "formAllowedVectorStoresHelp": "选择此组织可访问的向量存储。留空则允许访问所有向量存储", + "formAllowedVectorStoresPlaceholder": "选择向量存储(可选)", + "formAllowedMcpServers": "允许的 MCP 服务器", + "formAllowedMcpServersTooltip": "选择此组织默认可访问的 MCP 服务器和访问组。", + "formAllowedMcpServersHelp": "选择此组织可访问的 MCP 服务器和访问组。", + "formAllowedMcpServersPlaceholder": "选择 MCP 服务器和访问组(可选)", + "formMetadata": "元数据", + "deleteModalTitle": "删除组织?", + "deleteModalMessage": "确定要删除此组织吗?此操作无法撤销。", + "deleteModalResourceTitle": "组织信息", + "deleteSuccess": "组织已成功删除", + "createSuccess": "组织已成功创建" + }, + "passThroughInfo": { + "notFound": "未找到透传端点", + "backButton": "← 返回", + "pageTitle": "透传端点:{{path}}", + "tabOverview": "概览", + "labelPath": "路径", + "labelTarget": "目标", + "labelConfiguration": "配置", + "includeSubpath": "包含子路径", + "exactPath": "精确路径", + "authRequired": "需要认证", + "noAuth": "无需认证", + "httpMethods": "HTTP 方法:", + "allHttpMethodsSupported": "支持所有 HTTP 方法", + "costPerRequest": "每次请求费用:${{cost}}", + "labelHeaders": "请求头", + "headersConfigured_one": "已配置 {{count}} 个请求头", + "headersConfigured_other": "已配置 {{count}} 个请求头", + "labelGuardrails": "护栏", + "guardrailsConfigured_one": "已配置 {{count}} 个护栏", + "guardrailsConfigured_other": "已配置 {{count}} 个护栏", + "requestFields": "请求字段:{{fields}}", + "responseFields": "响应字段:{{fields}}", + "usesEntirePayload": "检查整个载荷", + "settingsTitle": "透传端点设置", + "editSettings": "编辑设置", + "deleteEndpoint": "删除端点", + "formTargetUrl": "目标 URL", + "formTargetUrlRequired": "请输入目标 URL", + "formHeadersJson": "请求头(JSON)", + "formHttpMethods": "HTTP 方法(可选)", + "allHttpMethodsDefault": "支持所有 HTTP 方法(默认)", + "selectedMethodsDesc": "仅 {{methods}} 请求将路由到此端点", + "selectMethodsPlaceholder": "选择方法(留空表示全部)", + "formIncludeSubpath": "包含子路径", + "formCostPerRequest": "每次请求费用", + "saveChanges": "保存更改", + "authenticationRequired": "需要认证", + "noHeadersConfigured": "未配置请求头", + "invalidJsonHeaders": "请求头的 JSON 格式无效", + "updateFailed": "更新透传端点失败", + "deleteSuccess": "透传端点已成功删除", + "deleteFailed": "删除透传端点失败" } }