From c8b27b6d52ddf1cf0f790228b26ac0c1473ac30e 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 07:10:56 +0900 Subject: [PATCH] feat(ui): i18n for create key form --- .../organisms/create_key_button.tsx | 364 ++++++++++-------- ui/litellm-dashboard/src/locales/en.json | 140 +++++++ ui/litellm-dashboard/src/locales/zh-CN.json | 140 +++++++ 3 files changed, 482 insertions(+), 162 deletions(-) diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx index ba7a1120e87..7e91b5627c4 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx @@ -12,6 +12,7 @@ import { Accordion, AccordionBody, AccordionHeader, Button, Col, Grid, Text, Tex import { Button as Button2, Form, Input, Modal, Radio, Select, Switch, Tag, Tooltip, Typography } from "antd"; import debounce from "lodash/debounce"; import React, { useCallback, useEffect, useState } from "react"; +import { Trans, useTranslation } from "react-i18next"; import { rolesWithWriteAccess } from "../../utils/roles"; import AgentSelector from "../agent_management/AgentSelector"; import { mapDisplayToInternalNames } from "../callback_info_helpers"; @@ -162,6 +163,7 @@ export const fetchUserModels = async ( * ───────────────────────────────────────────────────────────────────────── */ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOpenCreate, prefillData }) => { + const { t } = useTranslation(); const { accessToken, userId: userID, userRole, premiumUser } = useAuthorized(); const canEditGuardrails = premiumUser || (userRole != null && rolesWithWriteAccess.includes(userRole)); const { data: organizations, isLoading: isOrganizationsLoading } = useOrganizations(); @@ -378,14 +380,14 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp ); } - NotificationsManager.info("Making API Call"); + NotificationsManager.info(t("organisms.createKeyButton.notificationMakingApiCall")); setIsModalVisible(true); if (keyOwner === "you") { formValues.user_id = userID; } else if (keyOwner === "agent") { if (!selectedAgentId) { - NotificationsManager.fromBackend("Please select an agent"); + NotificationsManager.fromBackend(t("organisms.createKeyButton.notificationPleaseSelectAgent")); return; } formValues.agent_id = selectedAgentId; @@ -554,7 +556,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp setApiKey(response["key"]); setSoftBudget(response["soft_budget"]); - NotificationsManager.success("Virtual Key Created"); + NotificationsManager.success(t("organisms.createKeyButton.notificationVirtualKeyCreated")); form.resetFields(); setBudgetLimits([]); localStorage.removeItem("userData" + userID); @@ -566,7 +568,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp }; const handleCopy = () => { - NotificationsManager.success("Virtual Key copied to clipboard"); + NotificationsManager.success(t("organisms.createKeyButton.notificationVirtualKeyCopied")); }; // Fetch available models when team or auth changes. @@ -658,7 +660,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp setUserOptions(options); } catch (error) { console.error("Error fetching users:", error); - NotificationsManager.fromBackend("Failed to search for users"); + NotificationsManager.fromBackend(t("organisms.createKeyButton.notificationFailedToSearchUsers")); } finally { setUserSearchLoading(false); } @@ -684,19 +686,19 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
{userRole && rolesWithWriteAccess.includes(userRole) && ( )}
{/* Section 1: Key Ownership */}
- Key Ownership + {t("organisms.createKeyButton.sectionKeyOwnership")} - Owned By{" "} - + {t("organisms.createKeyButton.ownedByLabel")}{" "} + @@ -704,11 +706,14 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp className="mb-4" > setKeyOwner(e.target.value)} value={keyOwner}> - You - Service Account - {userRole === "Admin" && Another User} + {t("organisms.createKeyButton.ownerYou")} + {t("organisms.createKeyButton.ownerServiceAccount")} + {userRole === "Admin" && ( + {t("organisms.createKeyButton.ownerAnotherUser")} + )} - Agent New + {t("organisms.createKeyButton.ownerAgent")}{" "} + {t("organisms.createKeyButton.ownerAgentNew")} @@ -717,8 +722,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - User ID{" "} - + {t("organisms.createKeyButton.userIdLabel")}{" "} + @@ -728,7 +733,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp rules={[ { required: keyOwner === "another_user", - message: `Please input the user ID of the user you are assigning the key to`, + message: t("organisms.createKeyButton.userIdRuleMessage"), }, ]} > @@ -736,7 +741,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
setSelectedAgentId(value)} @@ -775,16 +784,14 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp value: a.agent_id, }))} /> -
- This key will be used by the selected agent to make requests to LiteLLM -
+
{t("organisms.createKeyButton.agentKeyDescription")}
)} - Organization{" "} - + {t("organisms.createKeyButton.organizationLabel")}{" "} + @@ -809,8 +816,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Team{" "} - + {t("organisms.createKeyButton.teamLabel")}{" "} + @@ -821,10 +828,10 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp rules={[ { required: keyOwner === "service_account", - message: "Please select a team for the service account", + message: t("organisms.createKeyButton.teamRuleMessage"), }, ]} - help={keyOwner === "service_account" ? "required" : ""} + help={keyOwner === "service_account" ? t("common.required") : ""} > = ({ team, teams, data, addKey, autoOp - Project{" "} - + {t("organisms.createKeyButton.projectLabel")}{" "} + @@ -879,8 +886,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp {isFormDisabled && (
- Please select a team to continue configuring your Virtual Key. If you do not see any teams, please - contact your Proxy Admin to either provide you with access to models or to add you to a team. + {t("organisms.createKeyButton.teamSelectionRequiredMessage")}
)} @@ -888,16 +894,18 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp {/* Section 2: Key Details */} {!isFormDisabled && (
- Key Details + {t("organisms.createKeyButton.sectionKeyDetails")} - {keyOwner === "you" || keyOwner === "another_user" ? "Key Name" : "Service Account ID"}{" "} + {keyOwner === "you" || keyOwner === "another_user" + ? t("organisms.createKeyButton.keyNameLabel") + : t("organisms.createKeyButton.serviceAccountIdLabel")}{" "} @@ -908,10 +916,13 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp rules={[ { required: true, - message: `Please input a ${keyOwner === "you" ? "key name" : "service account ID"}`, + message: + keyOwner === "you" + ? t("organisms.createKeyButton.keyAliasRuleMessageKeyName") + : t("organisms.createKeyButton.keyAliasRuleMessageServiceAccountId"), }, ]} - help="required" + help={t("common.required")} > @@ -919,8 +930,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Models{" "} - + {t("organisms.createKeyButton.modelsLabel")}{" "} + @@ -929,14 +940,14 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp rules={[]} help={ keyType === "management" || keyType === "read_only" - ? "Models field is disabled for this key type" - : "optional - leave empty to allow access to all models" + ? t("organisms.createKeyButton.modelsHelpDisabled") + : t("organisms.createKeyButton.modelsHelpOptional") } className="mt-4" > { @@ -984,27 +995,27 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp } }} > - - - @@ -1018,27 +1029,32 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
- Optional Settings + {t("organisms.createKeyButton.sectionOptionalSettings")} - Max Budget (USD){" "} - + {t("organisms.createKeyButton.maxBudgetLabel")}{" "} + } name="max_budget" - help={`Budget cannot exceed team max budget: $${team?.max_budget !== null && team?.max_budget !== undefined ? team?.max_budget : "unlimited"}`} + help={t("organisms.createKeyButton.maxBudgetHelp", { + value: + team?.max_budget !== null && team?.max_budget !== undefined ? team?.max_budget : "unlimited", + })} rules={[ { validator: async (_, value) => { if (value && team && team.max_budget !== null && value > team.max_budget) { throw new Error( - `Budget cannot exceed team max budget: $${formatNumberWithCommas(team.max_budget, 4)}`, + t("organisms.createKeyButton.maxBudgetValidatorError", { + value: formatNumberWithCommas(team.max_budget, 4), + }), ); } }, @@ -1051,14 +1067,19 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp className="mt-4" label={ - Reset Budget{" "} - + {t("organisms.createKeyButton.resetBudgetLabel")}{" "} + } name="budget_duration" - help={`Team Reset Budget: ${team?.budget_duration !== null && team?.budget_duration !== undefined ? team?.budget_duration : "None"}`} + help={t("organisms.createKeyButton.resetBudgetHelp", { + value: + team?.budget_duration !== null && team?.budget_duration !== undefined + ? team?.budget_duration + : t("common.none"), + })} > form.setFieldValue("budget_duration", value)} /> @@ -1066,8 +1087,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp className="mt-4" label={ - Budget Windows{" "} - + {t("organisms.createKeyButton.budgetWindowsLabel")}{" "} + @@ -1079,19 +1100,23 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp className="mt-4" label={ - Tokens per minute Limit (TPM){" "} - + {t("organisms.createKeyButton.tpmLabel")}{" "} + } name="tpm_limit" - help={`TPM cannot exceed team TPM limit: ${team?.tpm_limit !== null && team?.tpm_limit !== undefined ? team?.tpm_limit : "unlimited"}`} + help={t("organisms.createKeyButton.tpmHelp", { + value: team?.tpm_limit !== null && team?.tpm_limit !== undefined ? team?.tpm_limit : "unlimited", + })} rules={[ { validator: async (_, value) => { if (value && team && team.tpm_limit !== null && value > team.tpm_limit) { - throw new Error(`TPM limit cannot exceed team TPM limit: ${team.tpm_limit}`); + throw new Error( + t("organisms.createKeyButton.tpmValidatorError", { value: team.tpm_limit }), + ); } }, }, @@ -1111,19 +1136,23 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp className="mt-4" label={ - Requests per minute Limit (RPM){" "} - + {t("organisms.createKeyButton.rpmLabel")}{" "} + } name="rpm_limit" - help={`RPM cannot exceed team RPM limit: ${team?.rpm_limit !== null && team?.rpm_limit !== undefined ? team?.rpm_limit : "unlimited"}`} + help={t("organisms.createKeyButton.rpmHelp", { + value: team?.rpm_limit !== null && team?.rpm_limit !== undefined ? team?.rpm_limit : "unlimited", + })} rules={[ { validator: async (_, value) => { if (value && team && team.rpm_limit !== null && value > team.rpm_limit) { - throw new Error(`RPM limit cannot exceed team RPM limit: ${team.rpm_limit}`); + throw new Error( + t("organisms.createKeyButton.rpmValidatorError", { value: team.rpm_limit }), + ); } }, }, @@ -1142,8 +1171,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Guardrails{" "} - + {t("organisms.createKeyButton.guardrailsLabel")}{" "} + = ({ team, teams, data, addKey, autoOp className="mt-4" help={ canEditGuardrails - ? "Select existing guardrails or enter new ones" - : "Premium feature - Upgrade to set guardrails by key" + ? t("organisms.createKeyButton.guardrailsHelpPremium") + : t("organisms.createKeyButton.guardrailsHelpNonPremium") } > = ({ team, teams, data, addKey, autoOp style={{ width: "100%" }} disabled={!premiumUser} placeholder={ - !premiumUser ? "Premium feature - Upgrade to set policies by key" : "Select or enter policies" + !premiumUser + ? t("organisms.createKeyButton.policiesPlaceholderNonPremium") + : t("organisms.createKeyButton.policiesPlaceholderPremium") } options={policiesList.map((name) => ({ value: name, label: name }))} /> @@ -1239,8 +1274,8 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Prompts{" "} - + {t("organisms.createKeyButton.promptsLabel")}{" "} + = ({ team, teams, data, addKey, autoOp className="mt-4" help={ premiumUser - ? "Select existing prompts or enter new ones" - : "Premium feature - Upgrade to set prompts by key" + ? t("organisms.createKeyButton.promptsHelpPremium") + : t("organisms.createKeyButton.promptsHelpNonPremium") } > - MCP Settings + {t("organisms.createKeyButton.mcpSettingsHeader")} - Allowed MCP Servers{" "} - + {t("organisms.createKeyButton.allowedMcpServersLabel")}{" "} + } name="allowed_mcp_servers_and_groups" - help="Select MCP servers or access groups this key can access" + help={t("organisms.createKeyButton.allowedMcpServersHelp")} > form.setFieldValue("allowed_mcp_servers_and_groups", val)} value={form.getFieldValue("allowed_mcp_servers_and_groups")} accessToken={accessToken} teamId={selectedCreateKeyTeam?.team_id ?? null} - placeholder="Select MCP servers or access groups (optional)" + placeholder={t("organisms.createKeyButton.allowedMcpServersPlaceholder")} /> @@ -1431,26 +1468,26 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Agent Settings + {t("organisms.createKeyButton.agentSettingsHeader")} - Allowed Agents{" "} - + {t("organisms.createKeyButton.allowedAgentsLabel")}{" "} + } name="allowed_agents_and_groups" - help="Select agents or access groups this key can access" + help={t("organisms.createKeyButton.allowedAgentsHelp")} > form.setFieldValue("allowed_agents_and_groups", val)} value={form.getFieldValue("allowed_agents_and_groups")} accessToken={accessToken} - placeholder="Select agents or access groups (optional)" + placeholder={t("organisms.createKeyButton.allowedAgentsPlaceholder")} /> @@ -1459,7 +1496,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp {premiumUser ? ( - Logging Settings + {t("organisms.createKeyButton.loggingSettingsHeader")}
@@ -1476,12 +1513,14 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp ) : ( - Key-level logging settings is an enterprise feature, get in touch - - - https://www.litellm.ai/enterprise - - + + ), + }} + /> } placement="top" > @@ -1489,7 +1528,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
- Logging Settings + {t("organisms.createKeyButton.loggingSettingsHeader")}
@@ -1511,7 +1550,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Router Settings + {t("organisms.createKeyButton.routerSettingsHeader")}
@@ -1532,13 +1571,12 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp - Model Aliases + {t("organisms.createKeyButton.modelAliasesHeader")}
- Create custom aliases for models that can be used in API calls. This allows you to create - shortcuts for specific models. + {t("organisms.createKeyButton.modelAliasesDescription")} = ({ team, teams, data, addKey, autoOp - Key Lifecycle + {t("organisms.createKeyButton.keyLifecycleHeader")}
@@ -1573,24 +1611,26 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
- Advanced Settings + {t("organisms.createKeyButton.advancedSettingsHeader")} - Learn more about advanced settings in our{" "} - - documentation - - + + ), + }} + /> } > @@ -1626,7 +1666,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp
- Create Key + {t("organisms.createKeyButton.createKeyButton")}
@@ -1635,7 +1675,7 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp {/* Add the Create User Modal */} {isCreateUserModalVisible && ( setIsCreateUserModalVisible(false)} footer={null} @@ -1655,12 +1695,12 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp {apiKey && ( - Save your Key + {t("organisms.createKeyButton.saveKeyTitle")} {apiKey != null ? ( ) : ( - Key being created, this might take 30s + {t("organisms.createKeyButton.keyBeingCreated")} )} diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index b545159c4d5..2dfd91ed8ee 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -8163,6 +8163,146 @@ "durationRuleMessage": "Must be a duration like 30s, 30m, 24h, 2d, 1w, or 1mo", "expirationRequired": "Expiration is required for expired keys", "regenerateSuccess": "Virtual Key regenerated successfully" + }, + "createKeyButton": { + "createNewKey": "+ Create New Key", + "sectionKeyOwnership": "Key Ownership", + "sectionKeyDetails": "Key Details", + "sectionOptionalSettings": "Optional Settings", + "ownedByLabel": "Owned By", + "ownedByTooltip": "Select who will own this Virtual Key", + "ownerYou": "You", + "ownerServiceAccount": "Service Account", + "ownerAnotherUser": "Another User", + "ownerAgent": "Agent", + "ownerAgentNew": "New", + "userIdLabel": "User ID", + "userIdTooltip": "The user who will own this key and be responsible for its usage", + "userIdRuleMessage": "Please input the user ID of the user you are assigning the key to", + "userSearchPlaceholder": "Type email to search for users", + "userSearching": "Searching...", + "userNotFound": "No users found", + "createUserButton": "Create User", + "searchByEmailHint": "Search by email to find users", + "selectAgentLabel": "Select Agent", + "selectAgentPlaceholder": "Select an agent", + "agentKeyDescription": "This key will be used by the selected agent to make requests to LiteLLM", + "organizationLabel": "Organization", + "organizationTooltip": "The organization this key belongs to. Selecting an organization filters the available teams.", + "teamLabel": "Team", + "teamTooltip": "The team this key belongs to, which determines available models and budget limits", + "teamRuleMessage": "Please select a team for the service account", + "projectLabel": "Project", + "projectTooltip": "Assign this key to a project. Selecting a project will lock the team to the project's team.", + "teamSelectionRequiredMessage": "Please select a team to continue configuring your Virtual Key. If you do not see any teams, please contact your Proxy Admin to either provide you with access to models or to add you to a team.", + "keyNameLabel": "Key Name", + "serviceAccountIdLabel": "Service Account ID", + "keyNameTooltip": "A descriptive name to identify this key", + "serviceAccountIdTooltip": "Unique identifier for this service account", + "keyAliasRuleMessageKeyName": "Please input a key name", + "keyAliasRuleMessageServiceAccountId": "Please input a service account ID", + "modelsLabel": "Models", + "modelsTooltip": "Select which models this key can access. Choose 'All Team Models' to grant access to all models available to the team. Leave empty to allow access to all models.", + "modelsHelpDisabled": "Models field is disabled for this key type", + "modelsHelpOptional": "optional - leave empty to allow access to all models", + "modelsPlaceholder": "Select models", + "modelsAllTeam": "All Team Models", + "keyTypeLabel": "Key Type", + "keyTypeTooltip": "Select the type of key to determine what routes and operations this key can access", + "keyTypePlaceholder": "Select key type", + "keyTypeAiApis": "AI APIs", + "keyTypeAiApisDescription": "Can call only AI API routes (chat/completions, embeddings, etc.)", + "keyTypeManagement": "Management", + "keyTypeManagementDescription": "Can call only management routes (user/team/key management)", + "keyTypeFullAccess": "Full Access", + "keyTypeFullAccessDescription": "Can call all routes (AI APIs, Management, and read-only)", + "maxBudgetLabel": "Max Budget (USD)", + "maxBudgetTooltip": "Maximum amount in USD this key can spend. When reached, the key will be blocked from making further requests", + "maxBudgetHelp": "Budget cannot exceed team max budget: ${{value}}", + "maxBudgetValidatorError": "Budget cannot exceed team max budget: ${{value}}", + "resetBudgetLabel": "Reset Budget", + "resetBudgetTooltip": "How often the budget should reset. For example, setting 'daily' will reset the budget every 24 hours", + "resetBudgetHelp": "Team Reset Budget: {{value}}", + "budgetWindowsLabel": "Budget Windows", + "budgetWindowsTooltip": "Set multiple independent budget windows (e.g., hourly $10 AND monthly $200). Each window tracks spend separately and resets on its own schedule.", + "tpmLabel": "Tokens per minute Limit (TPM)", + "tpmTooltip": "Maximum number of tokens this key can process per minute. Helps control usage and costs", + "tpmHelp": "TPM cannot exceed team TPM limit: {{value}}", + "tpmValidatorError": "TPM limit cannot exceed team TPM limit: {{value}}", + "rpmLabel": "Requests per minute Limit (RPM)", + "rpmTooltip": "Maximum number of API requests this key can make per minute. Helps prevent abuse and manage load", + "rpmHelp": "RPM cannot exceed team RPM limit: {{value}}", + "rpmValidatorError": "RPM limit cannot exceed team RPM limit: {{value}}", + "guardrailsLabel": "Guardrails", + "guardrailsTooltip": "Apply safety guardrails to this key to filter content or enforce policies", + "guardrailsHelpPremium": "Select existing guardrails or enter new ones", + "guardrailsHelpNonPremium": "Premium feature - Upgrade to set guardrails by key", + "guardrailsPlaceholderNonPremium": "Premium feature - Upgrade to set guardrails by key", + "guardrailsPlaceholderPremium": "Select or enter guardrails", + "disableGlobalGuardrailsLabel": "Disable Global Guardrails", + "disableGlobalGuardrailsTooltip": "When enabled, this key will bypass any guardrails configured to run on every request (global guardrails)", + "disableGlobalGuardrailsHelpPremium": "Bypass global guardrails for this key", + "disableGlobalGuardrailsHelpNonPremium": "Premium feature - Upgrade to disable global guardrails by key", + "policiesLabel": "Policies", + "policiesTooltip": "Apply policies to this key to control guardrails and other settings", + "policiesHelpPremium": "Select existing policies or enter new ones", + "policiesHelpNonPremium": "Premium feature - Upgrade to set policies by key", + "policiesPlaceholderNonPremium": "Premium feature - Upgrade to set policies by key", + "policiesPlaceholderPremium": "Select or enter policies", + "promptsLabel": "Prompts", + "promptsTooltip": "Allow this key to use specific prompt templates", + "promptsHelpPremium": "Select existing prompts or enter new ones", + "promptsHelpNonPremium": "Premium feature - Upgrade to set prompts by key", + "promptsPlaceholderNonPremium": "Premium feature - Upgrade to set prompts by key", + "promptsPlaceholderPremium": "Select or enter prompts", + "accessGroupsLabel": "Access Groups", + "accessGroupsTooltip": "Assign access groups to this key. Access groups control which models, MCP servers, and agents this key can use", + "accessGroupsHelp": "Select access groups to assign to this key", + "accessGroupsPlaceholder": "Select access groups (optional)", + "passThroughRoutesLabel": "Allowed Pass Through Routes", + "passThroughRoutesTooltip": "Allow this key to use specific pass through routes", + "passThroughRoutesHelpPremium": "Select existing pass through routes or enter new ones", + "passThroughRoutesHelpNonPremium": "Premium feature - Upgrade to set pass through routes by key", + "passThroughRoutesPlaceholderNonPremium": "Premium feature - Upgrade to set pass through routes by key", + "passThroughRoutesPlaceholderPremium": "Select or enter pass through routes", + "vectorStoresLabel": "Allowed Vector Stores", + "vectorStoresTooltip": "Select which vector stores this key can access. If none selected, the key will have access to all available vector stores", + "vectorStoresHelp": "Select vector stores this key can access. Leave empty for access to all vector stores", + "vectorStoresPlaceholder": "Select vector stores (optional)", + "metadataLabel": "Metadata", + "metadataTooltip": "JSON object with additional information about this key. Used for tracking or custom logic", + "metadataPlaceholder": "Enter metadata as JSON", + "tagsLabel": "Tags", + "tagsTooltip": "Tags for tracking spend and/or doing tag-based routing. Used for analytics and filtering", + "tagsHelp": "Tags for tracking spend and/or doing tag-based routing.", + "tagsPlaceholder": "Select or enter tags", + "mcpSettingsHeader": "MCP Settings", + "allowedMcpServersLabel": "Allowed MCP Servers", + "allowedMcpServersTooltip": "Select which MCP servers or access groups this key can access", + "allowedMcpServersHelp": "Select MCP servers or access groups this key can access", + "allowedMcpServersPlaceholder": "Select MCP servers or access groups (optional)", + "agentSettingsHeader": "Agent Settings", + "allowedAgentsLabel": "Allowed Agents", + "allowedAgentsTooltip": "Select which agents or access groups this key can access", + "allowedAgentsHelp": "Select agents or access groups this key can access", + "allowedAgentsPlaceholder": "Select agents or access groups (optional)", + "loggingSettingsHeader": "Logging Settings", + "loggingSettingsEnterpriseTooltip": "Key-level logging settings is an enterprise feature, get in touch - https://www.litellm.ai/enterprise", + "routerSettingsHeader": "Router Settings", + "modelAliasesHeader": "Model Aliases", + "modelAliasesDescription": "Create custom aliases for models that can be used in API calls. This allows you to create shortcuts for specific models.", + "keyLifecycleHeader": "Key Lifecycle", + "advancedSettingsHeader": "Advanced Settings", + "advancedSettingsTooltip": "Learn more about advanced settings in our documentation", + "notificationFailedToSearchUsers": "Failed to search for users", + "notificationMakingApiCall": "Making API Call", + "notificationPleaseSelectAgent": "Please select an agent", + "notificationVirtualKeyCreated": "Virtual Key Created", + "notificationVirtualKeyCopied": "Virtual Key copied to clipboard", + "saveKeyTitle": "Save your Key", + "keyBeingCreated": "Key being created, this might take 30s", + "createUserModalTitle": "Create New User", + "createKeyButton": "Create Key" } }, "alerting": { diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index c05cd7e130c..09e3fbad33a 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -8163,6 +8163,146 @@ "durationRuleMessage": "请输入有效时长,如 30s、30m、24h、2d、1w 或 1mo", "expirationRequired": "已过期的密钥必须设置新的过期时间", "regenerateSuccess": "虚拟密钥重新生成成功" + }, + "createKeyButton": { + "createNewKey": "+ 新建密钥", + "sectionKeyOwnership": "密钥归属", + "sectionKeyDetails": "密钥详情", + "sectionOptionalSettings": "可选设置", + "ownedByLabel": "归属方", + "ownedByTooltip": "选择此虚拟密钥的归属方", + "ownerYou": "你", + "ownerServiceAccount": "服务账号", + "ownerAnotherUser": "其他用户", + "ownerAgent": "Agent", + "ownerAgentNew": "新", + "userIdLabel": "用户 ID", + "userIdTooltip": "此密钥的归属用户,负责该密钥的使用情况", + "userIdRuleMessage": "请输入要分配密钥的用户 ID", + "userSearchPlaceholder": "输入邮箱搜索用户", + "userSearching": "搜索中...", + "userNotFound": "未找到用户", + "createUserButton": "创建用户", + "searchByEmailHint": "通过邮箱搜索用户", + "selectAgentLabel": "选择 Agent", + "selectAgentPlaceholder": "选择一个 Agent", + "agentKeyDescription": "此密钥将由所选 Agent 用于向 LiteLLM 发起请求", + "organizationLabel": "组织", + "organizationTooltip": "此密钥所属的组织。选择组织后将筛选可用团队。", + "teamLabel": "团队", + "teamTooltip": "此密钥所属的团队,决定可用模型和预算限制", + "teamRuleMessage": "请为服务账号选择一个团队", + "projectLabel": "项目", + "projectTooltip": "将此密钥分配到某个项目。选择项目后,团队将锁定为该项目的团队。", + "teamSelectionRequiredMessage": "请先选择团队,再继续配置虚拟密钥。如果看不到任何团队,请联系代理管理员为你分配模型访问权限或将你添加到团队。", + "keyNameLabel": "密钥名称", + "serviceAccountIdLabel": "服务账号 ID", + "keyNameTooltip": "用于标识此密钥的描述性名称", + "serviceAccountIdTooltip": "此服务账号的唯一标识符", + "keyAliasRuleMessageKeyName": "请输入密钥名称", + "keyAliasRuleMessageServiceAccountId": "请输入服务账号 ID", + "modelsLabel": "模型", + "modelsTooltip": "选择此密钥可访问的模型。选择‘所有团队模型’可授权访问团队所有可用模型。留空则允许访问所有模型。", + "modelsHelpDisabled": "此密钥类型已禁用模型字段", + "modelsHelpOptional": "可选 - 留空则允许访问所有模型", + "modelsPlaceholder": "选择模型", + "modelsAllTeam": "所有团队模型", + "keyTypeLabel": "密钥类型", + "keyTypeTooltip": "选择密钥类型以决定此密钥可访问的路由和操作", + "keyTypePlaceholder": "选择密钥类型", + "keyTypeAiApis": "AI 接口", + "keyTypeAiApisDescription": "仅可调用 AI 接口路由(chat/completions、embeddings 等)", + "keyTypeManagement": "管理", + "keyTypeManagementDescription": "仅可调用管理路由(用户/团队/密钥管理)", + "keyTypeFullAccess": "完全访问", + "keyTypeFullAccessDescription": "可调用所有路由(AI 接口、管理及只读)", + "maxBudgetLabel": "最大预算(美元)", + "maxBudgetTooltip": "此密钥可使用的最大金额(美元)。达到上限后,该密钥将被阻止发起进一步请求。", + "maxBudgetHelp": "预算不得超过团队最大预算:${{value}}", + "maxBudgetValidatorError": "预算不得超过团队最大预算:${{value}}", + "resetBudgetLabel": "重置预算", + "resetBudgetTooltip": "预算重置频率。例如设置‘每天’将每 24 小时重置一次预算。", + "resetBudgetHelp": "团队重置预算:{{value}}", + "budgetWindowsLabel": "预算窗口", + "budgetWindowsTooltip": "设置多个独立预算窗口(例如每小时 $10 且每月 $200)。每个窗口独立跟踪花费并按各自计划重置。", + "tpmLabel": "每分钟 Token 限制(TPM)", + "tpmTooltip": "此密钥每分钟可处理的最大 Token 数量,有助于控制用量和成本", + "tpmHelp": "TPM 不得超过团队 TPM 限制:{{value}}", + "tpmValidatorError": "TPM 限制不得超过团队 TPM 限制:{{value}}", + "rpmLabel": "每分钟请求限制(RPM)", + "rpmTooltip": "此密钥每分钟可发起的最大 API 请求数,有助于防止滥用和管理负载", + "rpmHelp": "RPM 不得超过团队 RPM 限制:{{value}}", + "rpmValidatorError": "RPM 限制不得超过团队 RPM 限制:{{value}}", + "guardrailsLabel": "护栏", + "guardrailsTooltip": "为此密钥应用安全护栏以过滤内容或执行策略", + "guardrailsHelpPremium": "选择现有护栏或输入新护栏", + "guardrailsHelpNonPremium": "高级功能 - 升级后可按密钥设置护栏", + "guardrailsPlaceholderNonPremium": "高级功能 - 升级后可按密钥设置护栏", + "guardrailsPlaceholderPremium": "选择或输入护栏", + "disableGlobalGuardrailsLabel": "禁用全局护栏", + "disableGlobalGuardrailsTooltip": "启用后,此密钥将绕过配置为对每个请求运行的护栏(全局护栏)", + "disableGlobalGuardrailsHelpPremium": "为此密钥绕过全局护栏", + "disableGlobalGuardrailsHelpNonPremium": "高级功能 - 升级后可按密钥禁用全局护栏", + "policiesLabel": "策略", + "policiesTooltip": "为此密钥应用策略以控制护栏和其他设置", + "policiesHelpPremium": "选择现有策略或输入新策略", + "policiesHelpNonPremium": "高级功能 - 升级后可按密钥设置策略", + "policiesPlaceholderNonPremium": "高级功能 - 升级后可按密钥设置策略", + "policiesPlaceholderPremium": "选择或输入策略", + "promptsLabel": "提示词", + "promptsTooltip": "允许此密钥使用特定的提示词模板", + "promptsHelpPremium": "选择现有提示词或输入新提示词", + "promptsHelpNonPremium": "高级功能 - 升级后可按密钥设置提示词", + "promptsPlaceholderNonPremium": "高级功能 - 升级后可按密钥设置提示词", + "promptsPlaceholderPremium": "选择或输入提示词", + "accessGroupsLabel": "访问组", + "accessGroupsTooltip": "为此密钥分配访问组。访问组控制此密钥可使用的模型、MCP 服务器和 Agent。", + "accessGroupsHelp": "选择要分配给此密钥的访问组", + "accessGroupsPlaceholder": "选择访问组(可选)", + "passThroughRoutesLabel": "允许的透传路由", + "passThroughRoutesTooltip": "允许此密钥使用特定的透传路由", + "passThroughRoutesHelpPremium": "选择现有透传路由或输入新路由", + "passThroughRoutesHelpNonPremium": "高级功能 - 升级后可按密钥设置透传路由", + "passThroughRoutesPlaceholderNonPremium": "高级功能 - 升级后可按密钥设置透传路由", + "passThroughRoutesPlaceholderPremium": "选择或输入透传路由", + "vectorStoresLabel": "允许的向量存储", + "vectorStoresTooltip": "选择此密钥可访问的向量存储。若未选择,密钥将可访问所有可用向量存储。", + "vectorStoresHelp": "选择此密钥可访问的向量存储。留空则允许访问所有向量存储。", + "vectorStoresPlaceholder": "选择向量存储(可选)", + "metadataLabel": "元数据", + "metadataTooltip": "包含此密钥附加信息的 JSON 对象,用于跟踪或自定义逻辑", + "metadataPlaceholder": "以 JSON 格式输入元数据", + "tagsLabel": "标签", + "tagsTooltip": "用于跟踪花费和/或进行基于标签的路由。用于分析和筛选。", + "tagsHelp": "用于跟踪花费和/或进行基于标签的路由。", + "tagsPlaceholder": "选择或输入标签", + "mcpSettingsHeader": "MCP 设置", + "allowedMcpServersLabel": "允许的 MCP 服务器", + "allowedMcpServersTooltip": "选择此密钥可访问的 MCP 服务器或访问组", + "allowedMcpServersHelp": "选择此密钥可访问的 MCP 服务器或访问组", + "allowedMcpServersPlaceholder": "选择 MCP 服务器或访问组(可选)", + "agentSettingsHeader": "Agent 设置", + "allowedAgentsLabel": "允许的 Agent", + "allowedAgentsTooltip": "选择此密钥可访问的 Agent 或访问组", + "allowedAgentsHelp": "选择此密钥可访问的 Agent 或访问组", + "allowedAgentsPlaceholder": "选择 Agent 或访问组(可选)", + "loggingSettingsHeader": "日志设置", + "loggingSettingsEnterpriseTooltip": "密钥级日志设置是企业版功能,欢迎联系我们 - https://www.litellm.ai/enterprise", + "routerSettingsHeader": "路由器设置", + "modelAliasesHeader": "模型别名", + "modelAliasesDescription": "为模型创建自定义别名,可在 API 调用中使用。这样可以为特定模型创建快捷方式。", + "keyLifecycleHeader": "密钥生命周期", + "advancedSettingsHeader": "高级设置", + "advancedSettingsTooltip": "在我们的文档中了解更多高级设置", + "notificationFailedToSearchUsers": "搜索用户失败", + "notificationMakingApiCall": "正在发起 API 调用", + "notificationPleaseSelectAgent": "请选择一个 Agent", + "notificationVirtualKeyCreated": "虚拟密钥已创建", + "notificationVirtualKeyCopied": "虚拟密钥已复制到剪贴板", + "saveKeyTitle": "保存你的密钥", + "keyBeingCreated": "密钥正在创建中,可能需要 30 秒", + "createUserModalTitle": "创建新用户", + "createKeyButton": "创建密钥" } }, "alerting": {