From 8a6678ca5abb63b3738a868083e36d92151a19e9 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 02:06:52 +0900
Subject: [PATCH] feat(ui): i18n for vector store management; restore locale
keys dropped by earlier locale rewrite
The add_model batch rewrite of en.json/zh-CN.json accidentally deleted large
parts of the guardrails, viewLogs and playground namespaces and left duplicate
namespace blocks. Restore them by deep-merging the pre-rewrite locale state,
dedupe sibling keys, and fix the six test suites that exposed copy drift
introduced during extraction (Clear all, Total/Request, plural selection,
interpolation separators).
---
.../pricing_calculator/multi_cost_results.tsx | 4 +-
.../Modals/EditSSOSettingsModal.tsx | 2 +-
.../policies/impact_preview_alert.test.tsx | 6 +-
.../components/policies/policy_templates.tsx | 2 +-
.../CreateVectorStore.tsx | 78 +-
.../DocumentsTable.tsx | 27 +-
.../S3VectorsConfig.tsx | 42 +-
.../TestVectorStoreTab.tsx | 12 +-
.../VectorStoreForm.tsx | 133 +--
.../VectorStoreTable.tsx | 30 +-
.../src/components/vector_store_providers.tsx | 77 +-
.../LogDetailsDrawer/HistoryTree.tsx | 2 +-
ui/litellm-dashboard/src/locales/en.json | 828 +++++++++++++++++-
ui/litellm-dashboard/src/locales/zh-CN.json | 828 +++++++++++++++++-
14 files changed, 1877 insertions(+), 194 deletions(-)
diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx
index 21d82a41fcf..872ea8c1df0 100644
--- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx
+++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_cost_results.tsx
@@ -51,7 +51,9 @@ const SingleModelBreakdown: React.FC<{
- {t("costTracking.multiCostResults.totalPerRequest")}
+
+ {t("costTracking.multiCostResults.breakdownTotalPerRequest")}
+
{formatCost(result.cost_per_request)}
diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.tsx
index 6908b8a6b79..bc39b01ae49 100644
--- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.tsx
+++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.tsx
@@ -111,7 +111,7 @@ const EditSSOSettingsModal: React.FC
= ({ isVisible,
},
onError: (error) => {
NotificationsManager.fromBackend(
- t("settingsPages.editSSOSettingsModal.saveFailed", { error: parseErrorMessage(error) }),
+ t("settingsPages.editSSOSettingsModal.saveFailed", { error: String(parseErrorMessage(error)) }),
);
},
});
diff --git a/ui/litellm-dashboard/src/components/policies/impact_preview_alert.test.tsx b/ui/litellm-dashboard/src/components/policies/impact_preview_alert.test.tsx
index b79ca7b5681..4332a13752b 100644
--- a/ui/litellm-dashboard/src/components/policies/impact_preview_alert.test.tsx
+++ b/ui/litellm-dashboard/src/components/policies/impact_preview_alert.test.tsx
@@ -33,12 +33,12 @@ describe("ImpactPreviewAlert", () => {
describe("when scope is specific", () => {
it("should show the number of affected keys", () => {
renderWithProviders( );
- expect(screen.getByText(/3 keys/i)).toBeInTheDocument();
+ expect(screen.queryAllByText((_, node) => !!node?.textContent?.match(/3 keys/i)).length).toBeGreaterThan(0);
});
it("should show the number of affected teams", () => {
renderWithProviders( );
- expect(screen.getByText(/1 team\b/i)).toBeInTheDocument();
+ expect(screen.queryAllByText((_, node) => !!node?.textContent?.match(/1 team\b/i)).length).toBeGreaterThan(0);
});
it("should render sample key tags", () => {
@@ -66,7 +66,7 @@ describe("ImpactPreviewAlert", () => {
it("should use singular 'key' when exactly one key is affected", () => {
const oneKey = { affected_keys_count: 1, affected_teams_count: 0, sample_keys: ["sk-1"], sample_teams: [] };
renderWithProviders( );
- expect(screen.getByText(/1 key\b/i)).toBeInTheDocument();
+ expect(screen.queryAllByText((_, node) => !!node?.textContent?.match(/1 key\b/i)).length).toBeGreaterThan(0);
});
it("should not show a key section when there are no sample keys", () => {
diff --git a/ui/litellm-dashboard/src/components/policies/policy_templates.tsx b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx
index 8ec97774754..93d104d6045 100644
--- a/ui/litellm-dashboard/src/components/policies/policy_templates.tsx
+++ b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx
@@ -226,7 +226,7 @@ const PolicyTemplates: React.FC = ({
{t("policies.policyTemplates.categories")}
{selectedTags.size > 0 && (
- {t("common.clear")}
+ {t("policies.policyTemplates.clearAll")}
)}
diff --git a/ui/litellm-dashboard/src/components/vector_store_management/CreateVectorStore.tsx b/ui/litellm-dashboard/src/components/vector_store_management/CreateVectorStore.tsx
index c62ade3d2f2..33341ff05c4 100644
--- a/ui/litellm-dashboard/src/components/vector_store_management/CreateVectorStore.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_management/CreateVectorStore.tsx
@@ -1,4 +1,5 @@
import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
import { Card, Title, Text } from "@tremor/react";
import { Upload, Button, Select, Form, Alert, Tooltip, Input } from "antd";
import MessageManager from "@/components/molecules/message_manager";
@@ -25,6 +26,7 @@ interface CreateVectorStoreProps {
}
const CreateVectorStore: React.FC
= ({ accessToken, onSuccess }) => {
+ const { t } = useTranslation();
const [form] = Form.useForm();
const [documents, setDocuments] = useState([]);
const [isCreating, setIsCreating] = useState(false);
@@ -48,13 +50,13 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
].includes(file.type);
if (!isValidType) {
- MessageManager.error(`${file.name} is not a supported file type. Please upload PDF, TXT, DOCX, or MD files.`);
+ MessageManager.error(t("vectorStoreManagement.createVectorStore.unsupportedFileType", { name: file.name }));
return Upload.LIST_IGNORE;
}
const isLt50M = file.size / 1024 / 1024 < 50;
if (!isLt50M) {
- MessageManager.error(`${file.name} must be smaller than 50MB!`);
+ MessageManager.error(t("vectorStoreManagement.createVectorStore.fileTooLarge", { name: file.name }));
return Upload.LIST_IGNORE;
}
@@ -88,20 +90,20 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
const handleCreateVectorStore = async () => {
if (documents.length === 0) {
- MessageManager.warning("Please upload at least one document");
+ MessageManager.warning(t("vectorStoreManagement.createVectorStore.uploadAtLeastOne"));
return;
}
if (!selectedProvider) {
- MessageManager.warning("Please select a provider");
+ MessageManager.warning(t("vectorStoreManagement.createVectorStore.selectProvider"));
return;
}
// Validate provider-specific required fields
- const requiredFields = getProviderSpecificFields(selectedProvider).filter((field) => field.required);
+ const requiredFields = getProviderSpecificFields(selectedProvider, t).filter((field) => field.required);
for (const field of requiredFields) {
if (!providerParams[field.name]) {
- MessageManager.warning(`Please provide ${field.label}`);
+ MessageManager.warning(t("vectorStoreManagement.createVectorStore.provideField", { label: field.label }));
return;
}
}
@@ -109,17 +111,17 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
// S3 Vectors specific validation
if (selectedProvider === "s3_vectors") {
if (providerParams.vector_bucket_name && providerParams.vector_bucket_name.length < 3) {
- MessageManager.warning("Vector bucket name must be at least 3 characters");
+ MessageManager.warning(t("vectorStoreManagement.createVectorStore.bucketNameMinLength"));
return;
}
if (providerParams.index_name && providerParams.index_name.length > 0 && providerParams.index_name.length < 3) {
- MessageManager.warning("Index name must be at least 3 characters if provided");
+ MessageManager.warning(t("vectorStoreManagement.createVectorStore.indexNameMinLength"));
return;
}
}
if (!accessToken) {
- MessageManager.error("No access token available");
+ MessageManager.error(t("common.error"));
return;
}
@@ -165,7 +167,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
setIngestResults(results);
NotificationsManager.success(
- `Successfully created vector store with ${results.length} document(s). Vector Store ID: ${vectorStoreId}`,
+ t("vectorStoreManagement.createVectorStore.createSuccess", { count: results.length, vectorStoreId }),
);
if (onSuccess && vectorStoreId) {
@@ -179,7 +181,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
}, 3000);
} catch (error) {
console.error("Error creating vector store:", error);
- NotificationsManager.fromBackend(`Failed to create vector store: ${error}`);
+ NotificationsManager.fromBackend(t("vectorStoreManagement.createVectorStore.createFailed", { error }));
} finally {
setIsCreating(false);
}
@@ -188,26 +190,24 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
return (
-
Create Vector Store
-
- Upload documents and select a provider to create a new vector store with embedded content.
-
+ {t("vectorStoreManagement.createVectorStore.pageTitle")}
+ {t("vectorStoreManagement.createVectorStore.pageSubtitle")}
{/* Upload Area */}
- Step 1: Upload Documents
+ {t("vectorStoreManagement.createVectorStore.step1Title")}
- Upload one or more documents (PDF, TXT, DOCX, MD). Maximum file size: 50MB per file.
+ {t("vectorStoreManagement.createVectorStore.step1Subtitle")}
- Click or drag files to this area to upload
- Support for single or bulk upload. Supported formats: PDF, TXT, DOCX, MD
+ {t("vectorStoreManagement.createVectorStore.draggerText")}
+ {t("vectorStoreManagement.createVectorStore.draggerHint")}
@@ -215,7 +215,9 @@ const CreateVectorStore: React.FC
= ({ accessToken, onSu
{documents.length > 0 && (
- Uploaded Documents ({documents.length})
+
+ {t("vectorStoreManagement.createVectorStore.uploadedDocuments", { count: documents.length })}
+
@@ -225,9 +227,9 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
- Step 2: Configure Vector Store
+ {t("vectorStoreManagement.createVectorStore.step2Title")}
- Choose the provider and optionally provide a name and description for your vector store.
+ {t("vectorStoreManagement.createVectorStore.step2Subtitle")}
@@ -235,8 +237,8 @@ const CreateVectorStore: React.FC
= ({ accessToken, onSu
- Vector Store Name{" "}
-
+ {t("vectorStoreManagement.createVectorStore.vectorStoreNameLabel")}{" "}
+
@@ -245,7 +247,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
setVectorStoreName(e.target.value)}
- placeholder="e.g., Product Documentation, Customer Support KB"
+ placeholder={t("vectorStoreManagement.createVectorStore.vectorStoreNamePlaceholder")}
size="large"
className="rounded-md"
/>
@@ -254,8 +256,8 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
- Description{" "}
-
+ {t("common.description")}{" "}
+
@@ -264,7 +266,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
setVectorStoreDescription(e.target.value)}
- placeholder="e.g., Contains all product documentation and user guides"
+ placeholder={t("vectorStoreManagement.createVectorStore.descriptionPlaceholder")}
rows={2}
size="large"
className="rounded-md"
@@ -274,8 +276,8 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
- Provider{" "}
-
+ {t("vectorStoreManagement.createVectorStore.providerLabel")}{" "}
+
@@ -285,7 +287,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
@@ -329,7 +331,7 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
{/* Other Provider-specific fields */}
{selectedProvider !== "s3_vectors" &&
- getProviderSpecificFields(selectedProvider).map((field: VectorStoreFieldConfig) => {
+ getProviderSpecificFields(selectedProvider, t).map((field: VectorStoreFieldConfig) => {
if (field.type === "select") {
// For embedding model selection, we'd need to fetch available models
// For now, provide a text input as fallback
@@ -391,7 +393,9 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
loading={isCreating}
disabled={documents.length === 0 || !selectedProvider}
>
- {isCreating ? "Creating Vector Store..." : "Create Vector Store"}
+ {isCreating
+ ? t("vectorStoreManagement.createVectorStore.creating")
+ : t("vectorStoreManagement.createVectorStore.createButton")}
@@ -400,14 +404,16 @@ const CreateVectorStore: React.FC = ({ accessToken, onSu
{/* Success Message */}
{ingestResults.length > 0 && (
- Vector Store ID: {ingestResults[0]?.vector_store_id}
+ {t("vectorStoreManagement.createVectorStore.vectorStoreIdLabel")} {" "}
+ {ingestResults[0]?.vector_store_id}
- Documents Ingested: {ingestResults.length}
+ {t("vectorStoreManagement.createVectorStore.documentsIngestedLabel")} {" "}
+ {ingestResults.length}
}
diff --git a/ui/litellm-dashboard/src/components/vector_store_management/DocumentsTable.tsx b/ui/litellm-dashboard/src/components/vector_store_management/DocumentsTable.tsx
index c1ce57ad335..23a75b23ca1 100644
--- a/ui/litellm-dashboard/src/components/vector_store_management/DocumentsTable.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_management/DocumentsTable.tsx
@@ -1,4 +1,5 @@
import React from "react";
+import { useTranslation } from "react-i18next";
import { Table, Badge, Tooltip } from "antd";
import MessageManager from "@/components/molecules/message_manager";
import { EyeOutlined, CopyOutlined, DeleteOutlined } from "@ant-design/icons";
@@ -10,17 +11,19 @@ interface DocumentsTableProps {
}
const DocumentsTable: React.FC = ({ documents, onRemove }) => {
+ const { t } = useTranslation();
+
const handleCopyId = (uid: string) => {
navigator.clipboard.writeText(uid);
- MessageManager.success("Document ID copied to clipboard");
+ MessageManager.success(t("vectorStoreManagement.documentsTable.idCopied"));
};
const getStatusBadge = (status: DocumentUpload["status"]) => {
const statusConfig = {
- uploading: { color: "blue", text: "Uploading" },
- done: { color: "green", text: "Ready" },
- error: { color: "red", text: "Error" },
- removed: { color: "default", text: "Removed" },
+ uploading: { color: "blue", text: t("vectorStoreManagement.documentsTable.statusUploading") },
+ done: { color: "green", text: t("vectorStoreManagement.documentsTable.statusReady") },
+ error: { color: "red", text: t("common.error") },
+ removed: { color: "default", text: t("vectorStoreManagement.documentsTable.statusRemoved") },
};
const config = statusConfig[status];
@@ -36,7 +39,7 @@ const DocumentsTable: React.FC = ({ documents, onRemove })
const columns = [
{
- title: "Name",
+ title: t("common.name"),
dataIndex: "name",
key: "name",
render: (name: string, record: DocumentUpload) => (
@@ -47,31 +50,31 @@ const DocumentsTable: React.FC = ({ documents, onRemove })
),
},
{
- title: "Status",
+ title: t("common.status"),
dataIndex: "status",
key: "status",
width: 150,
render: (status: DocumentUpload["status"]) => getStatusBadge(status),
},
{
- title: "Actions",
+ title: t("common.actions"),
key: "actions",
width: 120,
render: (_: any, record: DocumentUpload) => (
-
+
console.log("View", record)}
/>
-
+
handleCopyId(record.uid)}
/>
-
+
onRemove(record.uid)}
@@ -89,7 +92,7 @@ const DocumentsTable: React.FC = ({ documents, onRemove })
rowKey="uid"
pagination={false}
locale={{
- emptyText: "No documents uploaded yet. Upload documents above to get started.",
+ emptyText: t("vectorStoreManagement.documentsTable.emptyText"),
}}
size="small"
/>
diff --git a/ui/litellm-dashboard/src/components/vector_store_management/S3VectorsConfig.tsx b/ui/litellm-dashboard/src/components/vector_store_management/S3VectorsConfig.tsx
index 0568f982bab..c131cd5aeb0 100644
--- a/ui/litellm-dashboard/src/components/vector_store_management/S3VectorsConfig.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_management/S3VectorsConfig.tsx
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from "react";
+import { useTranslation } from "react-i18next";
import { Alert, Form, Input, Select, Tooltip } from "antd";
import { InfoCircleOutlined } from "@ant-design/icons";
import { fetchAvailableModels, ModelGroup } from "../playground/llm_calls/fetch_models";
@@ -10,6 +11,7 @@ interface S3VectorsConfigProps {
}
const S3VectorsConfig: React.FC = ({ accessToken, providerParams, onParamsChange }) => {
+ const { t } = useTranslation();
const [embeddingModels, setEmbeddingModels] = useState([]);
const [isLoadingModels, setIsLoadingModels] = useState(false);
@@ -44,22 +46,22 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
<>
{/* S3 Vectors Setup Instructions */}
- AWS S3 Vectors allows you to store and query vector embeddings directly in S3:
+ {t("vectorStoreManagement.s3VectorsConfig.alertDescription")}
- Vector buckets and indexes will be automatically created if they don't exist
- Vector dimensions are auto-detected from your selected embedding model
- Ensure your AWS credentials have permissions for S3 Vectors operations
+ {t("vectorStoreManagement.s3VectorsConfig.alertItem1")}
+ {t("vectorStoreManagement.s3VectorsConfig.alertItem2")}
+ {t("vectorStoreManagement.s3VectorsConfig.alertItem3")}
- Learn more:{" "}
+ {t("vectorStoreManagement.s3VectorsConfig.alertItem4Prefix")}{" "}
- AWS S3 Vectors Documentation
+ {t("vectorStoreManagement.s3VectorsConfig.alertItem4Link")}
@@ -74,8 +76,8 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
- Vector Bucket Name{" "}
-
+ {t("vectorStoreManagement.s3VectorsConfig.vectorBucketNameLabel")}{" "}
+
@@ -86,14 +88,14 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
}
help={
providerParams.vector_bucket_name && providerParams.vector_bucket_name.length < 3
- ? "Bucket name must be at least 3 characters"
+ ? t("vectorStoreManagement.s3VectorsConfig.bucketNameHelp")
: undefined
}
>
handleFieldChange("vector_bucket_name", e.target.value)}
- placeholder="my-vector-bucket (min 3 chars)"
+ placeholder={t("vectorStoreManagement.s3VectorsConfig.vectorBucketNamePlaceholder")}
size="large"
className="rounded-md"
/>
@@ -103,8 +105,8 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
- Index Name{" "}
-
+ {t("vectorStoreManagement.s3VectorsConfig.indexNameLabel")}{" "}
+
@@ -116,14 +118,14 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
}
help={
providerParams.index_name && providerParams.index_name.length > 0 && providerParams.index_name.length < 3
- ? "Index name must be at least 3 characters if provided"
+ ? t("vectorStoreManagement.s3VectorsConfig.indexNameHelp")
: undefined
}
>
handleFieldChange("index_name", e.target.value)}
- placeholder="my-vector-index (optional, min 3 chars)"
+ placeholder={t("vectorStoreManagement.s3VectorsConfig.indexNamePlaceholder")}
size="large"
className="rounded-md"
/>
@@ -133,8 +135,8 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
- AWS Region{" "}
-
+ {t("vectorStoreManagement.s3VectorsConfig.awsRegionLabel")}{" "}
+
@@ -154,8 +156,8 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
- Embedding Model{" "}
-
+ {t("vectorStoreManagement.s3VectorsConfig.embeddingModelLabel")}{" "}
+
@@ -165,7 +167,7 @@ const S3VectorsConfig: React.FC = ({ accessToken, provider
handleFieldChange("embedding_model", value)}
- placeholder="Select an embedding model"
+ placeholder={t("vectorStoreManagement.s3VectorsConfig.embeddingModelPlaceholder")}
size="large"
showSearch
loading={isLoadingModels}
diff --git a/ui/litellm-dashboard/src/components/vector_store_management/TestVectorStoreTab.tsx b/ui/litellm-dashboard/src/components/vector_store_management/TestVectorStoreTab.tsx
index e96f149196e..fa1d2d4cbb0 100644
--- a/ui/litellm-dashboard/src/components/vector_store_management/TestVectorStoreTab.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_management/TestVectorStoreTab.tsx
@@ -1,4 +1,5 @@
import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
import { Card, Select, Typography } from "antd";
import { VectorStoreTester } from "./VectorStoreTester";
import { VectorStore } from "./types";
@@ -11,6 +12,7 @@ interface TestVectorStoreTabProps {
}
const TestVectorStoreTab: React.FC = ({ accessToken, vectorStores }) => {
+ const { t } = useTranslation();
const [selectedVectorStoreId, setSelectedVectorStoreId] = useState(
vectorStores.length > 0 ? vectorStores[0].vector_store_id : undefined,
);
@@ -18,7 +20,7 @@ const TestVectorStoreTab: React.FC = ({ accessToken, ve
if (!accessToken) {
return (
- Access token is required to test vector stores.
+ {t("vectorStoreManagement.testVectorStoreTab.accessTokenRequired")}
);
}
@@ -27,7 +29,7 @@ const TestVectorStoreTab: React.FC = ({ accessToken, ve
return (
- No vector stores available. Create one first to test it.
+ {t("vectorStoreManagement.testVectorStoreTab.noVectorStores")}
);
@@ -38,14 +40,14 @@ const TestVectorStoreTab: React.FC = ({ accessToken, ve
-
Select Vector Store
- Choose a vector store to test search queries against
+ {t("vectorStoreManagement.testVectorStoreTab.selectTitle")}
+ {t("vectorStoreManagement.testVectorStoreTab.selectSubtitle")}
= ({
accessToken,
credentials,
}) => {
+ const { t } = useTranslation();
const [form] = Form.useForm();
const [metadataJson, setMetadataJson] = useState("{}");
const [selectedProvider, setSelectedProvider] = useState("bedrock");
@@ -59,7 +61,7 @@ const VectorStoreForm: React.FC = ({
try {
metadata = metadataJson.trim() ? JSON.parse(metadataJson) : {};
} catch (e) {
- NotificationsManager.fromBackend("Invalid JSON in metadata field");
+ NotificationsManager.fromBackend(t("vectorStoreManagement.vectorStoreForm.invalidMetadataJson"));
return;
}
@@ -74,7 +76,7 @@ const VectorStoreForm: React.FC = ({
};
// pass all provider fields as litellm params dict
- const providerFields = getProviderSpecificFields(formValues.custom_llm_provider);
+ const providerFields = getProviderSpecificFields(formValues.custom_llm_provider, t);
const litellmParams = providerFields.reduce(
(acc, field) => {
// Special handling for Milvus: rename embedding_model to litellm_embedding_model
@@ -91,13 +93,13 @@ const VectorStoreForm: React.FC = ({
payload["litellm_params"] = litellmParams;
await vectorStoreCreateCall(accessToken, payload);
- NotificationsManager.success("Vector store created successfully");
+ NotificationsManager.success(t("vectorStoreManagement.vectorStoreForm.createSuccess"));
form.resetFields();
setMetadataJson("{}");
onSuccess();
} catch (error) {
console.error("Error creating vector store:", error);
- NotificationsManager.fromBackend("Error creating vector store: " + error);
+ NotificationsManager.fromBackend(t("vectorStoreManagement.vectorStoreForm.createFailed", { error }));
}
};
@@ -109,19 +111,25 @@ const VectorStoreForm: React.FC = ({
};
return (
-
+
- Provider{" "}
-
+ {t("vectorStoreManagement.vectorStoreForm.providerLabel")}{" "}
+
}
name="custom_llm_provider"
- rules={[{ required: true, message: "Please select a provider" }]}
+ rules={[{ required: true, message: t("vectorStoreManagement.vectorStoreForm.providerRequired") }]}
initialValue="bedrock"
>
setSelectedProvider(value)}>
@@ -157,20 +165,20 @@ const VectorStoreForm: React.FC = ({
{/* PG Vector Setup Instructions */}
{selectedProvider === "pg_vector" && (
- LiteLLM provides a server to connect to PG Vector. To use this provider:
+ {t("vectorStoreManagement.vectorStoreForm.pgVectorAlertDescription")}
- Deploy the litellm-pgvector server from:{" "}
+ {t("vectorStoreManagement.vectorStoreForm.pgVectorStep1")}{" "}
https://github.com/BerriAI/litellm-pgvector
- Configure your PostgreSQL database with pgvector extension
- Start the server and note the API base URL and API key
- Enter those details in the fields below
+ {t("vectorStoreManagement.vectorStoreForm.pgVectorStep2")}
+ {t("vectorStoreManagement.vectorStoreForm.pgVectorStep3")}
+ {t("vectorStoreManagement.vectorStoreForm.pgVectorStep4")}
}
@@ -183,24 +191,24 @@ const VectorStoreForm: React.FC = ({
{/* Vertex RAG Engine Setup Instructions */}
{selectedProvider === "vertex_rag_engine" && (
- To use Vertex AI RAG Engine:
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagAlertDescription")}
- Set up your Vertex AI RAG Engine corpus following the guide:{" "}
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagStep1")}{" "}
- Vertex AI RAG Engine Overview
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagStep1Link")}
- Create a corpus in your Google Cloud project
- Note the corpus ID from the Vertex AI console
- Enter the corpus ID in the Vector Store ID field below
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagStep2")}
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagStep3")}
+ {t("vectorStoreManagement.vectorStoreForm.vertexRagStep4")}
}
@@ -213,34 +221,25 @@ const VectorStoreForm: React.FC = ({
{/* Vertex AI Search Setup Instructions */}
{selectedProvider === "vertex_ai/search_api" && (
- To use Vertex AI Search (Discovery Engine):
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchAlertDescription")}
- Enable the Discovery Engine API on your Google Cloud project and create a data store following the
- guide:{" "}
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchStep1")}{" "}
- Create a Vertex AI Search data store
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchStep1Link")}
- Pick a supported location: global, us, or eu
-
- For most data store types (Cloud Storage, BigQuery, Media): copy the data store ID and enter it in
- the Vector Store ID field below.
-
-
- For website, healthcare, and connector-based sources (Drive, Gmail, Slack, Jira, etc.): create a
- search app on top of the data store, then copy the Engine ID and enter it in the
- Engine ID field. The Vector Store ID is still required as the LiteLLM-side name for this record, but
- it isn't used in the GCP URL when Engine ID is set.
-
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchStep2")}
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchStep3")}
+ {t("vectorStoreManagement.vectorStoreForm.vertexSearchStep4")}
}
@@ -253,30 +252,30 @@ const VectorStoreForm: React.FC = ({
- Vector Store ID{" "}
-
+ {t("vectorStoreManagement.vectorStoreForm.vectorStoreIdLabel")}{" "}
+
}
name="vector_store_id"
- rules={[{ required: true, message: "Please input the vector store ID from your api provider" }]}
+ rules={[{ required: true, message: t("vectorStoreManagement.vectorStoreForm.vectorStoreIdRequired") }]}
>
{/* Provider-specific fields */}
- {getProviderSpecificFields(selectedProvider).map((field: VectorStoreFieldConfig) => {
+ {getProviderSpecificFields(selectedProvider, t).map((field: VectorStoreFieldConfig) => {
if (field.type === "select") {
const selectOptions =
field.options ??
@@ -301,7 +300,16 @@ const VectorStoreForm: React.FC = ({
name={field.name}
initialValue={field.initialValue}
rules={
- field.required ? [{ required: true, message: `Please select the ${field.label.toLowerCase()}` }] : []
+ field.required
+ ? [
+ {
+ required: true,
+ message: t("vectorStoreManagement.vectorStoreForm.fieldSelectRequired", {
+ label: field.label.toLowerCase(),
+ }),
+ },
+ ]
+ : []
}
>
= ({
}
name={field.name}
rules={
- field.required ? [{ required: true, message: `Please input the ${field.label.toLowerCase()}` }] : []
+ field.required
+ ? [
+ {
+ required: true,
+ message: t("vectorStoreManagement.vectorStoreForm.fieldInputRequired", {
+ label: field.label.toLowerCase(),
+ }),
+ },
+ ]
+ : []
}
>
@@ -339,8 +356,8 @@ const VectorStoreForm: React.FC = ({
- Vector Store Name{" "}
-
+ {t("vectorStoreManagement.vectorStoreForm.vectorStoreNameLabel")}{" "}
+
@@ -350,15 +367,15 @@ const VectorStoreForm: React.FC = ({
-
+
- Existing Credentials{" "}
-
+ {t("vectorStoreManagement.vectorStoreForm.existingCredentialsLabel")}{" "}
+
@@ -367,11 +384,11 @@ const VectorStoreForm: React.FC = ({
>
(option?.label ?? "").toLowerCase().includes(input.toLowerCase())}
options={[
- { value: null, label: "None" },
+ { value: null, label: t("common.none") },
...credentials.map((credential) => ({
value: credential.credential_name,
label: credential.credential_name,
@@ -384,8 +401,8 @@ const VectorStoreForm: React.FC = ({
- Metadata{" "}
-
+ {t("vectorStoreManagement.vectorStoreForm.metadataLabel")}{" "}
+
@@ -401,10 +418,10 @@ const VectorStoreForm: React.FC = ({
- Cancel
+ {t("common.cancel")}
- Create
+ {t("common.create")}
diff --git a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTable.tsx b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTable.tsx
index 180c2485ab5..a971dd572ef 100644
--- a/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTable.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_management/VectorStoreTable.tsx
@@ -10,6 +10,7 @@ import {
import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "@tremor/react";
import { Tooltip } from "antd";
import React from "react";
+import { useTranslation } from "react-i18next";
import TableIconActionButton from "../common_components/IconActionButton/TableIconActionButtons/TableIconActionButton";
import { getProviderLogoAndName } from "../provider_info_helpers";
import { VectorStore } from "./types";
@@ -22,11 +23,12 @@ interface VectorStoreTableProps {
}
const VectorStoreTable: React.FC = ({ data, onView, onEdit, onDelete }) => {
+ const { t } = useTranslation();
const [sorting, setSorting] = React.useState([{ id: "created_at", desc: true }]);
const columns: ColumnDef[] = [
{
- header: "Vector Store ID",
+ header: t("vectorStoreManagement.vectorStoreTable.colVectorStoreId"),
accessorKey: "vector_store_id",
cell: ({ row }) => {
const vectorStore = row.original;
@@ -43,7 +45,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Name",
+ header: t("common.name"),
accessorKey: "vector_store_name",
cell: ({ row }) => {
const vectorStore = row.original;
@@ -55,7 +57,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Description",
+ header: t("common.description"),
accessorKey: "vector_store_description",
cell: ({ row }) => {
const vectorStore = row.original;
@@ -67,7 +69,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Files",
+ header: t("vectorStoreManagement.vectorStoreTable.colFiles"),
accessorKey: "vector_store_metadata",
cell: ({ row }) => {
const vectorStore = row.original;
@@ -77,12 +79,14 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
return - ;
}
- const filenames = ingestedFiles.map((file) => file.filename || file.file_url || "Unknown").join(", ");
+ const filenames = ingestedFiles.map((file) => file.filename || file.file_url || t("common.unknown")).join(", ");
const displayText =
ingestedFiles.length === 1
- ? ingestedFiles[0].filename || ingestedFiles[0].file_url || "1 file"
- : `${ingestedFiles.length} files`;
+ ? ingestedFiles[0].filename ||
+ ingestedFiles[0].file_url ||
+ t("vectorStoreManagement.vectorStoreTable.oneFile")
+ : t("vectorStoreManagement.vectorStoreTable.nFiles", { count: ingestedFiles.length });
return (
@@ -92,7 +96,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Provider",
+ header: t("vectorStoreManagement.vectorStoreTable.colProvider"),
accessorKey: "custom_llm_provider",
cell: ({ row }) => {
const vectorStore = row.original;
@@ -106,7 +110,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Created At",
+ header: t("common.createdAt"),
accessorKey: "created_at",
sortingFn: "datetime",
cell: ({ row }) => {
@@ -115,7 +119,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
},
},
{
- header: "Updated At",
+ header: t("common.updatedAt"),
accessorKey: "updated_at",
sortingFn: "datetime",
cell: ({ row }) => {
@@ -132,12 +136,12 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
onEdit(vectorStore.vector_store_id)}
/>
onDelete(vectorStore.vector_store_id)}
/>
@@ -217,7 +221,7 @@ const VectorStoreTable: React.FC = ({ data, onView, onEdi
-
No vector stores found
+
{t("vectorStoreManagement.vectorStoreTable.noVectorStores")}
diff --git a/ui/litellm-dashboard/src/components/vector_store_providers.tsx b/ui/litellm-dashboard/src/components/vector_store_providers.tsx
index fb1f32a00e0..49ebe492d9c 100644
--- a/ui/litellm-dashboard/src/components/vector_store_providers.tsx
+++ b/ui/litellm-dashboard/src/components/vector_store_providers.tsx
@@ -1,3 +1,5 @@
+import type { TFunction } from "i18next";
+
export enum VectorStoreProviders {
Bedrock = "Amazon Bedrock",
S3Vectors = "Amazon S3 Vectors",
@@ -45,22 +47,21 @@ export interface VectorStoreFieldConfig {
initialValue?: string;
}
-// Provider-specific field configurations
-export const vectorStoreProviderFields: Record = {
+export const getVectorStoreProviderFields = (t: TFunction): Record => ({
bedrock: [],
pg_vector: [
{
name: "api_base",
- label: "API Base",
- tooltip: "Enter the base URL of your deployed litellm-pgvector server (e.g., http://your-server:8000)",
+ label: t("vectorStoreProviders.pgVector.apiBaseLabel"),
+ tooltip: t("vectorStoreProviders.pgVector.apiBaseTooltip"),
placeholder: "http://your-deployed-server:8000",
required: true,
type: "text",
},
{
name: "api_key",
- label: "API Key",
- tooltip: "Enter the API key from your deployed litellm-pgvector server",
+ label: t("vectorStoreProviders.pgVector.apiKeyLabel"),
+ tooltip: t("vectorStoreProviders.pgVector.apiKeyTooltip"),
placeholder: "your-deployed-api-key",
required: true,
type: "password",
@@ -70,16 +71,16 @@ export const vectorStoreProviderFields: Record
"vertex_ai/search_api": [
{
name: "vertex_project",
- label: "Vertex Project",
- tooltip: "Google Cloud project ID that hosts the Vertex AI Search data store.",
+ label: t("vectorStoreProviders.vertexAiSearch.vertexProjectLabel"),
+ tooltip: t("vectorStoreProviders.vertexAiSearch.vertexProjectTooltip"),
placeholder: "my-gcp-project-id",
required: true,
type: "text",
},
{
name: "vertex_location",
- label: "Vertex Location",
- tooltip: "Vertex AI Search data store location. Must be one of global, us, or eu.",
+ label: t("vectorStoreProviders.vertexAiSearch.vertexLocationLabel"),
+ tooltip: t("vectorStoreProviders.vertexAiSearch.vertexLocationTooltip"),
required: true,
type: "select",
options: [
@@ -91,17 +92,16 @@ export const vectorStoreProviderFields: Record
},
{
name: "vertex_collection_id",
- label: "Collection ID (optional)",
- tooltip: "Discovery Engine collection ID. Leave blank to use the default collection.",
+ label: t("vectorStoreProviders.vertexAiSearch.vertexCollectionIdLabel"),
+ tooltip: t("vectorStoreProviders.vertexAiSearch.vertexCollectionIdTooltip"),
placeholder: "e.g. my-custom-collection",
required: false,
type: "text",
},
{
name: "vertex_engine_id",
- label: "Engine ID (optional)",
- tooltip:
- "Search app (engine) ID. Required for website, healthcare, and connector-based data stores (Workspace, Slack, Jira, etc.) because these sources route search through an engine. Leave blank to query the data store directly.",
+ label: t("vectorStoreProviders.vertexAiSearch.vertexEngineIdLabel"),
+ tooltip: t("vectorStoreProviders.vertexAiSearch.vertexEngineIdTooltip"),
placeholder: "e.g. my-search-app_1234567890",
required: false,
type: "text",
@@ -110,8 +110,8 @@ export const vectorStoreProviderFields: Record
openai: [
{
name: "api_key",
- label: "API Key",
- tooltip: "Enter your OpenAI API key",
+ label: t("vectorStoreProviders.openai.apiKeyLabel"),
+ tooltip: t("vectorStoreProviders.openai.apiKeyTooltip"),
placeholder: "sk-...",
required: true,
type: "password",
@@ -120,16 +120,16 @@ export const vectorStoreProviderFields: Record
azure: [
{
name: "api_key",
- label: "API Key",
- tooltip: "Enter your Azure OpenAI API key",
+ label: t("vectorStoreProviders.azure.apiKeyLabel"),
+ tooltip: t("vectorStoreProviders.azure.apiKeyTooltip"),
placeholder: "your-azure-api-key",
required: true,
type: "password",
},
{
name: "api_base",
- label: "API Base",
- tooltip: "Enter your Azure OpenAI endpoint (e.g., https://your-resource.openai.azure.com/)",
+ label: t("vectorStoreProviders.azure.apiBaseLabel"),
+ tooltip: t("vectorStoreProviders.azure.apiBaseTooltip"),
placeholder: "https://your-resource.openai.azure.com/",
required: true,
type: "text",
@@ -138,25 +138,24 @@ export const vectorStoreProviderFields: Record
milvus: [
{
name: "api_key",
- label: "API Key",
- tooltip:
- "To obtain a token, you should use a colon (:) to concatenate the username and password that you use to access your Milvus instance (e.g., username:password)",
+ label: t("vectorStoreProviders.milvus.apiKeyLabel"),
+ tooltip: t("vectorStoreProviders.milvus.apiKeyTooltip"),
placeholder: "username:password or api key",
required: true,
type: "password",
},
{
name: "api_base",
- label: "API Base",
- tooltip: "Enter your Milvus endpoint (e.g., https://your-milvus-endpoint.com/)",
+ label: t("vectorStoreProviders.milvus.apiBaseLabel"),
+ tooltip: t("vectorStoreProviders.milvus.apiBaseTooltip"),
placeholder: "https://your-milvus-endpoint.com/",
required: true,
type: "text",
},
{
name: "embedding_model",
- label: "Embedding Model",
- tooltip: "Select the embedding model to use",
+ label: t("vectorStoreProviders.milvus.embeddingModelLabel"),
+ tooltip: t("vectorStoreProviders.milvus.embeddingModelTooltip"),
placeholder: "text-embedding-3-small",
required: true,
type: "select",
@@ -165,38 +164,38 @@ export const vectorStoreProviderFields: Record
s3_vectors: [
{
name: "vector_bucket_name",
- label: "Vector Bucket Name",
- tooltip: "S3 bucket name for vector storage (will be auto-created if it doesn't exist)",
+ label: t("vectorStoreProviders.s3Vectors.vectorBucketNameLabel"),
+ tooltip: t("vectorStoreProviders.s3Vectors.vectorBucketNameTooltip"),
placeholder: "my-vector-bucket",
required: true,
type: "text",
},
{
name: "index_name",
- label: "Index Name",
- tooltip: "Name for the vector index (optional, will be auto-generated if not provided)",
+ label: t("vectorStoreProviders.s3Vectors.indexNameLabel"),
+ tooltip: t("vectorStoreProviders.s3Vectors.indexNameTooltip"),
placeholder: "my-vector-index",
required: false,
type: "text",
},
{
name: "aws_region_name",
- label: "AWS Region",
- tooltip: "AWS region where the S3 bucket is located (e.g., us-west-2)",
+ label: t("vectorStoreProviders.s3Vectors.awsRegionLabel"),
+ tooltip: t("vectorStoreProviders.s3Vectors.awsRegionTooltip"),
placeholder: "us-west-2",
required: true,
type: "text",
},
{
name: "embedding_model",
- label: "Embedding Model",
- tooltip: "Select the embedding model to use for vector generation",
+ label: t("vectorStoreProviders.s3Vectors.embeddingModelLabel"),
+ tooltip: t("vectorStoreProviders.s3Vectors.embeddingModelTooltip"),
placeholder: "text-embedding-3-small",
required: true,
type: "select",
},
],
-};
+});
export const getVectorStoreProviderLogoAndName = (providerValue: string): { logo: string; displayName: string } => {
if (!providerValue) {
@@ -219,6 +218,6 @@ export const getVectorStoreProviderLogoAndName = (providerValue: string): { logo
return { logo, displayName };
};
-export const getProviderSpecificFields = (providerValue: string): VectorStoreFieldConfig[] => {
- return vectorStoreProviderFields[providerValue] || [];
+export const getProviderSpecificFields = (providerValue: string, t: TFunction): VectorStoreFieldConfig[] => {
+ return getVectorStoreProviderFields(t)[providerValue] || [];
};
diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/HistoryTree.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/HistoryTree.tsx
index 26e1bb513d4..e281b79537a 100644
--- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/HistoryTree.tsx
+++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/HistoryTree.tsx
@@ -50,7 +50,7 @@ export function HistoryTree({ messages }: HistoryTreeProps) {
)}
- {t("viewLogs.historyTree.history_other", { count: messages.length })}
+ {t("viewLogs.historyTree.history", { count: messages.length })}
diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json
index 11710d0509b..0dfdeb470b9 100644
--- a/ui/litellm-dashboard/src/locales/en.json
+++ b/ui/litellm-dashboard/src/locales/en.json
@@ -1590,6 +1590,258 @@
"updateSuccess": "Guardrail updated successfully",
"updateFailed": "Failed to update guardrail",
"notFound": "Guardrail not found"
+ },
+ "guardrailGardenTab": "Guardrail Garden",
+ "guardrailsTab": "Guardrails",
+ "testPlaygroundTab": "Test Playground",
+ "submittedGuardrailsTab": "Submitted Guardrails",
+ "addNewGuardrail": "+ Add New Guardrail",
+ "addProviderGuardrail": "Add Provider Guardrail",
+ "createCustomCodeGuardrail": "Create Custom Code Guardrail",
+ "deleteGuardrailTitle": "Delete Guardrail",
+ "deleteGuardrailMessage": "Are you sure you want to delete guardrail: {{name}}? This action cannot be undone.",
+ "guardrailInfoTitle": "Guardrail Information",
+ "labelId": "ID",
+ "labelMode": "Mode",
+ "labelDefaultOn": "Default On",
+ "deleteSuccess": "Guardrail \"{{name}}\" deleted successfully",
+ "deleteFailed": "Failed to delete guardrail",
+ "teamGuardrailsTab": {
+ "statusActive": "Active",
+ "statusPendingReview": "Pending Review",
+ "statusRejected": "Rejected",
+ "teamLabel": "Team: {{team}}",
+ "modelLabel": "Model:",
+ "submittedLabel": "Submitted:",
+ "forwardApiKey": "Forward API Key",
+ "review": "Review",
+ "approve": "Approve",
+ "reject": "Reject",
+ "staticHeaders": "Static headers",
+ "noStaticHeaders": "No static headers configured.",
+ "submittedBy": "Submitted by {{by}} on {{at}}",
+ "closeDetailPanel": "Close detail panel",
+ "endpoint": "Endpoint",
+ "method": "Method",
+ "forwardLiteLLMApiKey": "Forward LiteLLM API Key",
+ "forwardKeyDesc": "When enabled, the caller's LiteLLM API key is forwarded as an Authorization header to your guardrail endpoint. This allows your guardrail to authenticate model calls using the original caller's credentials.",
+ "staticHeadersDesc": "Sent with every request to the guardrail.",
+ "removeHeader": "Remove {{name}}",
+ "headerNamePlaceholder": "Header name (e.g. X-API-Key)",
+ "headerValuePlaceholder": "Value",
+ "forwardClientHeaders": "Forward client headers",
+ "forwardClientHeadersDesc": "Allowed header names to forward from the client request to the guardrail (e.g. x-request-id).",
+ "noForwardClientHeaders": "No forward client headers configured.",
+ "extraHeaderPlaceholder": "e.g. x-request-id",
+ "equivalentConfig": "Equivalent config",
+ "guardrailInfoNote": "This guardrail runs on a separate instance. It receives the user request and forwards the result to the next step in the pipeline. See LiteLLM Generic Guardrail API docs for configuration details.",
+ "testEndpoint": "Test Endpoint",
+ "approveGuardrailTitle": "Approve Guardrail",
+ "rejectGuardrailTitle": "Reject Guardrail",
+ "approveGuardrailConfirm": "Are you sure you want to approve \"{{name}}\"? This will make it active and available for use.",
+ "rejectGuardrailConfirm": "Are you sure you want to reject \"{{name}}\"? This will mark it as rejected and notify the team.",
+ "totalSubmitted": "Total Submitted",
+ "searchPlaceholder": "Search guardrails...",
+ "filterAllStatus": "All Status",
+ "addGuardrail": "Add Guardrail",
+ "loadingSubmissions": "Loading submissions…",
+ "noGuardrailsMatch": "No guardrails match your filters.",
+ "failedToLoadSubmissions": "Failed to load submissions",
+ "forwardApiKeyEnabled": "Forward API key enabled",
+ "forwardApiKeyDisabled": "Forward API key disabled",
+ "failedToUpdateForwardApiKey": "Failed to update forward API key",
+ "staticHeadersUpdated": "Static headers updated",
+ "failedToUpdateStaticHeaders": "Failed to update static headers",
+ "forwardClientHeadersUpdated": "Forward client headers updated",
+ "failedToUpdateForwardClientHeaders": "Failed to update forward client headers",
+ "guardrailApproved": "Guardrail approved",
+ "failedToApproveGuardrail": "Failed to approve guardrail",
+ "guardrailRejected": "Guardrail rejected",
+ "failedToRejectGuardrail": "Failed to reject guardrail",
+ "submitModalTitle": "Submit Guardrail for Review",
+ "submitForReview": "Submit for Review",
+ "submitCallout": "Your guardrail will be sent for admin review before it becomes active.",
+ "guardrailSubmitted": "Guardrail submitted for review",
+ "formTeam": "Team",
+ "formTeamRequired": "Select a team",
+ "formGuardrailName": "Guardrail Name",
+ "formGuardrailNameRequired": "Enter a guardrail name",
+ "formGuardrailNamePlaceholder": "e.g. pii-detection",
+ "formMode": "Mode",
+ "formModeRequired": "Select a mode",
+ "modePreCall": "Pre Call",
+ "modePostCall": "Post Call",
+ "modeDuringCall": "During Call",
+ "formApiBaseUrl": "API Base URL",
+ "formApiBaseUrlRequired": "Enter the API base URL",
+ "formApiBaseUrlInvalid": "Must be a valid URL",
+ "formApiBaseUrlPlaceholder": "https://your-guardrail-api.com/v1/check",
+ "formExtraParams": "Additional litellm_params (optional)",
+ "formExtraParamsTooltip": "JSON object merged into litellm_params. e.g. forward_api_key, headers, model, unreachable_fallback",
+ "formExtraParamsPlaceholder": "{\"forward_api_key\": true, \"headers\": {\"X-Custom\": \"value\"}}",
+ "formMustBeJsonObject": "Must be a JSON object",
+ "formInvalidJson": "Invalid JSON",
+ "formGuardrailInfo": "Guardrail Info (optional)",
+ "formGuardrailInfoPlaceholder": "{\"description\": \"Detects PII in requests\"}"
+ },
+ "addGuardrailForm": {
+ "modalTitle": "Create guardrail",
+ "guardrailNameLabel": "Guardrail Name",
+ "guardrailNameRequired": "Please enter a guardrail name",
+ "guardrailNamePlaceholder": "Enter a name for this guardrail",
+ "providerLabel": "Guardrail Provider",
+ "providerRequired": "Please select a provider",
+ "providerPlaceholder": "Select a guardrail provider",
+ "modeLabel": "Mode",
+ "modeTooltip": "How the guardrail should be applied",
+ "modeRequired": "Please select a mode",
+ "recommended": "Recommended",
+ "alwaysOnLabel": "Always On",
+ "alwaysOnTooltip": "If enabled, this guardrail will be applied to all requests by default.",
+ "skipSystemMsgLabel": "Skip system messages in guardrail",
+ "skipSystemMsgTooltip": "Unified guardrails only: omit role: system from guardrail evaluation input (OpenAI chat + Anthropic messages). The model still receives full messages. Use global default follows litellm_settings.skip_system_message_in_guardrail.",
+ "skipToolMsgLabel": "Skip tool messages in guardrail",
+ "skipToolMsgTooltip": "Unified guardrails only: omit role: tool from guardrail evaluation input (OpenAI chat + Anthropic messages). The model still receives full messages. Use global default follows litellm_settings.skip_tool_message_in_guardrail.",
+ "useGlobalDefault": "Use global default",
+ "yesExcludeFromScan": "Yes — exclude from guardrail scan",
+ "noAlwaysInclude": "No — always include in scan",
+ "modeDesc": {
+ "pre_call": "Before LLM Call - Runs before the LLM call and checks the input (Recommended)",
+ "during_call": "During LLM Call - Runs in parallel with the LLM call, with response held until check completes",
+ "post_call": "After LLM Call - Runs after the LLM call and checks only the output",
+ "logging_only": "Logging Only - Only runs on logging callbacks without affecting the LLM call",
+ "pre_mcp_call": "Before MCP Tool Call - Runs before MCP tool execution and validates tool calls",
+ "during_mcp_call": "During MCP Tool Call - Runs in parallel with MCP tool execution for monitoring"
+ },
+ "stepBasicInfo": "Basic Info",
+ "stepTopics": "Topics",
+ "stepPatterns": "Patterns",
+ "stepKeywords": "Keywords",
+ "stepEndpointSettings": "Endpoint Settings (Optional)",
+ "stepPiiConfig": "PII Configuration",
+ "stepProviderConfig": "Provider Configuration",
+ "skip": "Skip",
+ "addAndContinue": "Add & Continue →",
+ "continueArrow": "Continue →",
+ "createGuardrailButton": "Create Guardrail",
+ "endpointSettingsDesc": "Configure settings for a specific call type. Most guardrails don't need this — skip it unless you're using a specific endpoint like /v1/realtime.",
+ "callTypeLabel": "Call type",
+ "callTypePlaceholder": "Select a call type",
+ "moreCallTypesSoon": "More call types coming soon.",
+ "realtimeSettingsTitle": "/v1/realtime settings",
+ "endSessionLabel": "End session after X violations",
+ "endSessionDesc": "Automatically close the session after this many guardrail violations. Leave empty to never auto-close.",
+ "onViolationLabel": "On violation",
+ "violationWarn": "Warn",
+ "violationEndSession": "End session",
+ "violationWarnDesc": "Bot speaks the message, session continues",
+ "violationEndSessionDesc": "Bot speaks the message, connection closes immediately",
+ "violationMessageLabel": "Message the user hears",
+ "violationMessageDesc": "What the bot says aloud when this guardrail fires. Falls back to the default violation message if empty.",
+ "violationMessagePlaceholder": "e.g. I'm not able to continue this conversation. Please contact us at 1-800-774-2678.",
+ "failedToLoadConfig": "Failed to load guardrail configuration",
+ "selectAtLeastOnePii": "Please select at least one PII entity to continue",
+ "configureAtLeastOneFilter": "Please configure at least one content filter setting (category, pattern, keyword, or competitor intent)",
+ "invalidJsonConfig": "Invalid JSON in configuration",
+ "addAtLeastOneCriterion": "Add at least one evaluation criterion",
+ "weightsMustSum100": "Criterion weights must sum to 100% (currently {{weightTotal}}%)",
+ "addAtLeastOneRule": "Add at least one tool permission rule",
+ "createSuccess": "Guardrail created successfully",
+ "createFailed": "Failed to create guardrail: {{error}}"
+ },
+ "guardrailOptionalParams": {
+ "title": "Optional Parameters",
+ "defaultDescription": "Configure additional settings for this guardrail provider",
+ "enterValue": "Enter {{key}} value",
+ "selectValue": "Select {{key}} value",
+ "selectCategoryPlaceholder": "Select category to configure",
+ "selectCategoryHint": "Select a category to add threshold configuration",
+ "fieldRequired": "{{fieldKey}} is required"
+ },
+ "guardrailProviderFields": {
+ "loadFailed": "Failed to load provider parameters",
+ "loadingTip": "Loading provider parameters...",
+ "noFields": "No configuration fields available for this provider.",
+ "fieldRequired": "{{fieldKey}} is required"
+ },
+ "guardrailTable": {
+ "colGuardrailId": "Guardrail ID",
+ "colName": "Name",
+ "colProvider": "Provider",
+ "colMode": "Mode",
+ "colDefaultOn": "Default On",
+ "defaultOn": "Default On",
+ "defaultOff": "Default Off",
+ "deleteTooltip": "Delete guardrail",
+ "configDeleteTooltip": "Config guardrail cannot be deleted on the dashboard. Please delete it from the config file.",
+ "configDeleteAriaLabel": "Delete guardrail (config)",
+ "unnamedGuardrail": "Unnamed Guardrail",
+ "noGuardrails": "No guardrails found"
+ },
+ "lLMJudgeFields": {
+ "description": "After each LLM response, the Judge Model scores it 0–100 against your criteria. If the weighted average falls below the threshold, the response is blocked (or logged).",
+ "judgeModelLabel": "Judge Model",
+ "judgeModelTooltip": "The LLM that reads each response and grades it. Pick a capable model — it never sees end-user data beyond what the LLM returned.",
+ "judgeModelRequired": "Select a judge model",
+ "judgeModelPlaceholder": "Select a model",
+ "minScoreLabel": "Minimum Score to Pass",
+ "minScoreTooltip": "0–100. If the weighted average of criterion scores falls below this, the guardrail triggers. 80 is a good default.",
+ "onFailureLabel": "On Failure",
+ "onFailureTooltip": "Block: return HTTP 422 when the score is too low. Log: record the result but let the response through.",
+ "onFailureBlock": "Block (return 422)",
+ "onFailureLog": "Log only",
+ "criteriaLabel": "Evaluation Criteria",
+ "criteriaTooltip": "Each criterion is something the judge checks. Weights must add up to 100%.",
+ "criterionNameRequired": "Enter criterion name",
+ "criterionNamePlaceholder": "Criterion name (e.g. Policy accuracy)",
+ "weightLabel": "Weight",
+ "weightTooltip": "How much this criterion counts toward the final score. All weights must add up to 100%.",
+ "weightRequired": "Enter weight",
+ "criterionDescRequired": "Describe what to check",
+ "criterionDescPlaceholder": "What should the judge check for this criterion?",
+ "addCriterion": "Add Criterion",
+ "weightsTotal": "Weights total: {{weightTotal}}%",
+ "weightsMustSum": "must add up to 100%"
+ },
+ "piiComponents": {
+ "filterByCategory": "Filter by category",
+ "selectCategoriesPlaceholder": "Select categories to filter by",
+ "quickActions": "Quick Actions",
+ "quickActionsTooltip": "Apply action to all PII types at once",
+ "unselectAll": "Unselect All",
+ "selectAllMask": "Select All & Mask",
+ "selectAllBlock": "Select All & Block",
+ "piiTypeHeader": "PII Type",
+ "actionHeader": "Action",
+ "noMatch": "No PII types match your filter criteria"
+ },
+ "piiConfiguration": {
+ "title": "Configure PII Protection",
+ "itemsSelected_one": "{{count}} item selected",
+ "itemsSelected_other": "{{count}} items selected"
+ },
+ "toolPermissionRulesEditor": {
+ "title": "LiteLLM Tool Permission Guardrail",
+ "subtitle": "Provide regex patterns (e.g., ^mcp__github_.*$) for tool names or types and optionally constrain payload fields.",
+ "addRule": "Add Rule",
+ "noRules": "No tool rules added yet",
+ "ruleLabel": "Rule {{index}}",
+ "ruleId": "Rule ID",
+ "toolName": "Tool Name (optional)",
+ "toolType": "Tool Type (optional)",
+ "decision": "Decision",
+ "allow": "Allow",
+ "deny": "Deny",
+ "restrictArgs": "+ Restrict tool arguments (optional)",
+ "argConstraints": "Argument constraints (dot or array paths)",
+ "addConstraint": "+ Add another constraint",
+ "defaultAction": "Default action",
+ "onDisallowedAction": "On disallowed action",
+ "onDisallowedTooltip": "Block returns an error when a forbidden tool is invoked. Rewrite strips the tool call but lets the rest of the response continue.",
+ "block": "Block",
+ "rewrite": "Rewrite",
+ "violationMessage": "Violation message (optional)",
+ "violationMessagePlaceholder": "This violates our org policy..."
}
},
"keyValueInput": {
@@ -2662,7 +2914,113 @@
"collapseRow": "Collapse row",
"hideJson": "Hide JSON",
"showJson": "Show JSON",
- "copied": "Copied!"
+ "copied": "Copied!",
+ "colAction": "Action",
+ "colChangedBy": "Changed By"
+ },
+ "auditLogDrawer": {
+ "tableKeys": "Keys",
+ "tableTeams": "Teams",
+ "tableUsers": "Users",
+ "tableOrganizations": "Organizations",
+ "tableModels": "Models",
+ "copyJson": "Copy JSON",
+ "noDifferingFields": "No differing fields detected",
+ "tokenLabel": "Token:",
+ "spendLabel": "Spend:",
+ "maxBudgetLabel": "Max Budget:",
+ "before": "Before",
+ "after": "After",
+ "labelTable": "Table",
+ "labelObjectId": "Object ID",
+ "labelChangedBy": "Changed By",
+ "labelApiKeyHash": "API Key (Hash)"
+ },
+ "configInfoMessage": {
+ "title": "Request/Response Data Not Available",
+ "description": "To view request and response details, enable prompt storage in your LiteLLM configuration by adding the following to your proxy_config.yaml file, or toggle the setting in Admin Settings → Logging Settings .",
+ "note": "Note: This will only affect new requests after the configuration change."
+ },
+ "costBreakdownViewer": {
+ "title": "Cost Breakdown",
+ "cached": "Cached",
+ "inputCost": "Input Cost",
+ "outputCost": "Output Cost",
+ "cacheReadCost": "Cache Read Cost",
+ "cacheWriteCost": "Cache Write Cost",
+ "toolUsageCost": "Tool Usage Cost",
+ "tokens": "tokens",
+ "promptTokens": "prompt tokens",
+ "completionTokens": "completion tokens",
+ "originalLlmCost": "Original LLM Cost",
+ "discount": "Discount",
+ "discountAmount": "Discount Amount",
+ "margin": "Margin",
+ "finalCalculatedCost": "Final Calculated Cost"
+ },
+ "errorViewer": {
+ "title": "Error Details",
+ "type": "Type",
+ "message": "Message",
+ "unknownError": "Unknown Error",
+ "unknownErrorOccurred": "Unknown error occurred",
+ "traceback": "Traceback",
+ "collapseAll": "Collapse All",
+ "expandAll": "Expand All",
+ "copyTraceback": "Copy traceback"
+ },
+ "evalViewer": {
+ "title": "LLM Judge Results",
+ "colCriterion": "Criterion",
+ "colWeight": "Weight",
+ "colScore": "Score",
+ "colWeighted": "Weighted",
+ "weightedTooltip": "Score × Weight — how much each criterion contributes to the final score",
+ "colComment": "Comment",
+ "passed": "PASSED",
+ "failed": "FAILED",
+ "overallScoreTooltip": "Weighted average of all criterion scores. Each criterion has a weight (%) set when the eval was created — higher-weight criteria count more toward the final score.",
+ "threshold": "threshold",
+ "judge": "Judge",
+ "iter": "Iter",
+ "judgeError": "Judge error",
+ "scoreNoCriterion": "Score: {{score}} — no per-criterion breakdown available."
+ },
+ "bedrockGuardrailDetails": {
+ "detected": "detected",
+ "notDetected": "not detected",
+ "textGuarded": "text guarded {{guarded}}/{{total}}",
+ "imagesGuarded": "images guarded {{guarded}}/{{total}}",
+ "action": "Action",
+ "actionReason": "Action Reason",
+ "blockedResponse": "Blocked Response",
+ "coverage": "Coverage",
+ "usage": "Usage",
+ "outputs": "Outputs",
+ "nonTextOutput": "(non-text output)",
+ "assessmentTitle": "Assessment #{{number}}",
+ "wordPolicy": "Word Policy",
+ "customWords": "Custom Words",
+ "managedWordLists": "Managed Word Lists",
+ "contentPolicy": "Content Policy",
+ "colType": "Type",
+ "colAction": "Action",
+ "colDetected": "Detected",
+ "colStrength": "Strength",
+ "colConfidence": "Confidence",
+ "contextualGrounding": "Contextual Grounding",
+ "colScore": "Score",
+ "colThreshold": "Threshold",
+ "sensitiveInformation": "Sensitive Information",
+ "piiEntities": "PII Entities",
+ "customRegexes": "Custom Regexes",
+ "topicPolicy": "Topic Policy",
+ "invocationMetrics": "Invocation Metrics",
+ "latencyMs": "Latency (ms)",
+ "textCoverage": "text {{guarded}}/{{total}}",
+ "imagesCoverage": "images {{guarded}}/{{total}}",
+ "automatedReasoningFindings": "Automated Reasoning Findings",
+ "rawResponse": "Raw Bedrock Guardrail Response"
}
},
"userAgentActivity": {
@@ -3278,7 +3636,7 @@
"invalidJsonStdioEnv": "Invalid JSON in stdio env configuration",
"stdioRequiresCommand": "Stdio transport requires a command",
"invalidJsonTokenValidation": "Invalid JSON in Token Validation Rules",
- "oauthTokenPersistFailed": "MCP Server updated, but failed to persist OAuth token{{message}}",
+ "oauthTokenPersistFailed": "MCP Server updated, but failed to persist OAuth token: {{message}}",
"updateSuccess": "MCP Server updated successfully",
"updateFailed": "Failed to update MCP Server{{message}}",
"tabServerConfig": "Server Configuration",
@@ -3541,6 +3899,297 @@
"verdictGap": "Gap — should have been blocked",
"verdictFalsePositive": "False positive — incorrectly blocked",
"llmResponse": "LLM response:"
+ },
+ "a2AMetrics": {
+ "header": "A2A Metadata",
+ "totalLatency": "Total latency",
+ "timeToFirstToken": "Time to first token",
+ "clickToCopy": "Click to copy: {{id}}",
+ "taskPrefix": "Task: ",
+ "sessionPrefix": "Session: ",
+ "details": "Details",
+ "statusMessage": "Status Message:",
+ "taskId": "Task ID:",
+ "sessionId": "Session ID:",
+ "customMetadata": "Custom Metadata:"
+ },
+ "additionalModelSettings": {
+ "useAdvancedParams": "Use Advanced Parameters",
+ "simulateFailure": "Simulate failure to test fallbacks",
+ "simulateFailureDesc": "Causes the first request to fail so the router tries fallbacks (if configured). Use this to verify your fallback setup.",
+ "simulateFailureNote": "Behavior can differ when keys, teams, or router settings are configured. Learn more ",
+ "simulateFailureAriaLabel": "Help: Simulate failure to test fallbacks",
+ "temperature": "Temperature",
+ "temperatureTooltip": "Controls randomness. Lower values make output more deterministic, higher values more creative.",
+ "maxTokens": "Max Tokens",
+ "maxTokensTooltip": "Maximum number of tokens to generate in the response."
+ },
+ "agentBuilderView": {
+ "title": "Agent Builder",
+ "saveAgent": "Save Agent",
+ "buildAgentsSubtitle": "Build Agents that pass your compliance requirements.",
+ "experimentalBanner": "Agent Builder is experimental and may change or be removed without notice. We'd love your feedback—email us at product@berri.ai .",
+ "agentsLabel": "Agents",
+ "addAgentAriaLabel": "Add agent",
+ "newAgent": "New agent",
+ "noAgentsYet": "No agents yet. Add an agent to get started.",
+ "signInRequired": "Sign in to use Agent Builder.",
+ "tabConfigure": "Configure",
+ "tabChat": "Chat",
+ "tabBatchTest": "Batch Test",
+ "tabConnect": "Connect",
+ "missingModelIdWarning": "This agent cannot be updated or deleted here (missing model id). Manage it from Models & Endpoints.",
+ "agentNameLabel": "Agent name",
+ "agentNamePlaceholder": "My Agent",
+ "systemPromptLabel": "System prompt",
+ "systemPromptPlaceholder": "You are a helpful assistant...",
+ "defaultSystemPrompt": "You are a helpful assistant.",
+ "underlyingLlmLabel": "Underlying LLM",
+ "temperatureLabel": "Temperature",
+ "maxTokensLabel": "Max tokens",
+ "mcpServersLabel": "MCP servers",
+ "mcpServersPlaceholder": "Select MCP servers to attach (same format as chat completions API)",
+ "mcpServersSaved_one": "{{count}} MCP server saved. Use the same tools array in chat completions when calling this agent.",
+ "mcpServersSaved_other": "{{count}} MCP servers saved. Use the same tools array in chat completions when calling this agent.",
+ "updateAgent": "Update Agent",
+ "testInChat": "Test in Chat",
+ "saveAgentFirst": "Save an agent first to test in Chat.",
+ "selectAgentForBatchTest": "Select an agent to run batch tests.",
+ "selectAgentToConnect": "Select an agent to see how to connect.",
+ "proxyBaseUrl": "Proxy base URL",
+ "callYourAgent": "Call your agent (cURL)",
+ "createKeyTitle": "Create a key for this agent",
+ "createKeyDesc": "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}} .",
+ "createKeyButton": "Create key for this agent",
+ "keyCreationDisabled": "Key creation is disabled for your account.",
+ "keyCreated": "Key created. It is shown in the cURL example above — copy the snippet to use it.",
+ "failedToLoadAgents": "Failed to load agents",
+ "nameAndModelRequired": "Name and underlying model are required",
+ "failedToSaveAgent": "Failed to save agent",
+ "agentUpdated": "Agent updated successfully",
+ "failedToUpdateAgent": "Failed to update agent",
+ "virtualKeyCreated": "Virtual key created. Use it in the curl example below.",
+ "keyCreatedNoValue": "Key created but value not returned",
+ "failedToCreateKey": "Failed to create key for agent",
+ "deleteAgentTitle": "Delete agent",
+ "deleteAgentConfirm": "Are you sure you want to delete \"{{name}}\"? This cannot be undone.",
+ "agentDeleted": "Agent deleted",
+ "failedToDeleteAgent": "Failed to delete agent"
+ },
+ "audioRenderer": {
+ "browserNotSupported": "Your browser does not support the audio element."
+ },
+ "chatImageRenderer": {
+ "uploadedImageAlt": "User uploaded image"
+ },
+ "chatImageUpload": {
+ "attachTooltip": "Attach image or PDF"
+ },
+ "chatMessageBubble": {
+ "generatedImageAlt": "Generated image"
+ },
+ "chatUi": {
+ "requestCancelled": "Request cancelled",
+ "pleaseUploadImage": "Please upload at least one image for editing",
+ "pleaseUploadAudio": "Please upload an audio file for transcription",
+ "pleaseSelectAgent": "Please select an agent to send a message",
+ "pleaseSelectMCPServer": "Please select an MCP server to test",
+ "pleaseSelectMCPTool": "Please select an MCP tool to call",
+ "waitForToolSchema": "Please wait for tool schema to load",
+ "fillRequiredParameters": "Please fill in all required parameters",
+ "pleaseSelectModel": "Please select a model before sending a request",
+ "pleaseProvideVirtualKey": "Please provide a Virtual Key or select Current UI Session",
+ "failedToProcessImage": "Failed to process image. Please try again.",
+ "toolExecutedSuccessfully": "Tool executed successfully.",
+ "errorFetchingResponse": "Error fetching response: {{error}}",
+ "chatHistoryCleared": "Chat history cleared.",
+ "accessDenied": "Access Denied",
+ "askProxyAdminForAccess": "Ask your proxy admin for access to test models",
+ "configurations": "Configurations",
+ "virtualKeySource": "Virtual Key Source",
+ "currentUiSession": "Current UI Session",
+ "virtualKeyLabel": "Virtual Key",
+ "enterCustomVirtualKey": "Enter custom Virtual Key",
+ "customProxyBaseUrl": "Custom Proxy Base URL",
+ "fill": "Fill",
+ "customProxyUrlPlaceholder": "Optional: Enter custom proxy URL (e.g., http://localhost:5000)",
+ "apiCallsSentTo": "API calls will be sent to: {{url}}",
+ "endpointTypeLabel": "Endpoint Type",
+ "voiceLabel": "Voice",
+ "selectModelLabel": "Select Model",
+ "advancedParamsTooltip": "Advanced parameters are only supported for chat models currently",
+ "modelSettings": "Model Settings",
+ "selectModelPlaceholder": "Select a Model",
+ "enterCustomModel": "Enter custom model",
+ "enterCustomModelName": "Enter custom model name",
+ "selectAgentLabel": "Select Agent",
+ "selectAgentPlaceholder": "Select an Agent",
+ "noAgentsFound": "No agents found. Create agents via /v1/agents endpoint.",
+ "tagsLabel": "Tags",
+ "mcpServerLabel": "MCP Server",
+ "mcpServersLabel": "MCP Servers",
+ "mcpServerTooltipDirect": "Select an MCP server or toolset to test tools directly.",
+ "mcpServerTooltip": "Select MCP servers or toolsets to use in your conversation.",
+ "selectMCPServerPlaceholder": "Select MCP server",
+ "selectMCPServersPlaceholder": "Select MCP servers",
+ "allMCPServers": "All MCP Servers",
+ "useAllMCPServers": "Use all available MCP servers",
+ "toolsetsGroup": "Toolsets",
+ "toolsetBadge": "Toolset",
+ "toolCount": "({{count}} tools)",
+ "serversGroup": "Servers",
+ "selectToolLabel": "Select Tool",
+ "selectToolPlaceholder": "Select a tool to call",
+ "limitToolsFor": "Limit tools for {{serverName}}:",
+ "allToolsDefault": "All tools (default)",
+ "serverRequiresApiKey": "{{serverName}} requires your API key",
+ "connected": "Connected",
+ "reconnect": "Reconnect",
+ "connectButton": "Connect",
+ "vectorStoreLabel": "Vector Store",
+ "vectorStoreTooltip": "Select vector store(s) to use for this LLM API call. You can set up your vector store here .",
+ "guardrailsLabel": "Guardrails",
+ "guardrailsTooltip": "Select guardrail(s) to use for this LLM API call. You can set up your guardrails here .",
+ "policiesLabel": "Policies",
+ "policiesTooltip": "Select policy/policies to apply to this LLM API call. Policies define which guardrails are applied based on conditions. You can set up your policies here .",
+ "testKeyTitle": "Test Key",
+ "chatTitle": "Chat",
+ "clearChat": "Clear Chat",
+ "getCode": "Get Code",
+ "emptyStateHint": "Start a conversation, generate an image, or handle audio",
+ "assistant": "Assistant",
+ "dragImagesToUpload": "Click or drag images to upload",
+ "imageUploadHint": "Support for PNG, JPG, JPEG formats. Multiple images supported.",
+ "uploadPreviewAlt": "Upload preview {{index}}",
+ "addMore": "Add more",
+ "dragAudioToUpload": "Click or drag audio file to upload",
+ "audioUploadHint": "Support for MP3, MP4, MPEG, MPGA, M4A, WAV, WEBM formats. Max file size: 25 MB.",
+ "removeButton": "Remove",
+ "runningPythonCode": "Running Python code...",
+ "codeInterpreterActive": "Code Interpreter Active",
+ "disableButton": "Disable",
+ "samplePrompt1": "Generate sample sales data CSV and create a chart",
+ "samplePrompt2": "Create a PNG bar chart comparing AI gateway providers including LiteLLM",
+ "samplePrompt3": "Generate a CSV of LLM pricing data and visualize it as a line chart",
+ "suggestPromptA2A1": "What can you help me with?",
+ "suggestPromptA2A2": "Tell me about yourself",
+ "suggestPromptA2A3": "What tasks can you perform?",
+ "suggestPrompt1": "Write me a poem",
+ "suggestPrompt2": "Explain quantum computing",
+ "suggestPrompt3": "Draft a polite email requesting a meeting",
+ "codeInterpreterEnabledTooltip": "Code Interpreter enabled (click to disable)",
+ "enableCodeInterpreterTooltip": "Enable Code Interpreter",
+ "codeInterpreterEnabledNotice": "Code Interpreter enabled!",
+ "placeholderChat": "Type your message... (Shift+Enter for new line)",
+ "placeholderA2A": "Send a message to the A2A agent...",
+ "placeholderImageEdits": "Describe how you want to edit the image...",
+ "placeholderSpeech": "Enter text to convert to speech...",
+ "placeholderTranscription": "Optional: Add context or prompt for transcription...",
+ "placeholderImage": "Describe the image you want to generate...",
+ "loadingToolSchema": "Loading tool schema...",
+ "generatedCodeTitle": "Generated Code",
+ "sdkTypeLabel": "SDK Type",
+ "openAiSdk": "OpenAI SDK",
+ "azureSdk": "Azure SDK",
+ "copyToClipboard": "Copy to Clipboard",
+ "toolsetsInfoTitle": "How Toolsets Work",
+ "toolsetsInfoIntro": "Toolsets are named collections of specific tools from one or more MCP servers. Instead of exposing all tools from a server, a toolset gives an agent exactly the tools it needs.",
+ "toolsetsHowToUseTitle": "How to use a toolset:",
+ "toolsetsStep1": "Select a Toolset (purple badge) from the MCP Servers dropdown.",
+ "toolsetsStep2": "The tool picker will show only the tools included in that toolset.",
+ "toolsetsStep3": "Select a tool and fill in its parameters, then send.",
+ "toolsetsStep4": "The tool call is routed to the correct underlying MCP server automatically.",
+ "toolsetsExample": "Example: A \"GitHub Read-only\" toolset might include only list_repos and get_file from a GitHub MCP server — preventing agents from making writes.",
+ "toolsetsCreatingTitle": "Creating toolsets:",
+ "toolsetsCreatingDesc": "Admins can create and manage toolsets from the MCP page → Toolsets tab. Toolsets can then be assigned to keys and teams to scope their tool access."
+ },
+ "codeInterpreterOutput": {
+ "pythonCodeExecuted": "Python Code Executed",
+ "loadingImage": "Loading image...",
+ "generatedChart": "Generated chart",
+ "imageNotAvailable": "Image not available"
+ },
+ "codeInterpreterTool": {
+ "title": "Code Interpreter",
+ "tooltipDesc": "Run Python code to generate files, charts, and analyze data. Container is created automatically.",
+ "onlyOpenAIWarning": "Code Interpreter is only available for OpenAI models",
+ "onlyOpenAINotice": "Code Interpreter is currently only supported for OpenAI models.",
+ "requestSupportLink": "Request support for other providers"
+ },
+ "filePreviewCard": {
+ "uploadPreview": "Upload preview",
+ "pdf": "PDF",
+ "image": "Image"
+ },
+ "mcpEventsDisplay": {
+ "listTools": "List tools",
+ "toolCall": "Tool call",
+ "request": "Request",
+ "approved": "Approved",
+ "response": "Response"
+ },
+ "realtimePlayground": {
+ "title": "Realtime Voice Chat",
+ "selectModelFirst": "Please select a model first",
+ "connectedToApi": "Connected to realtime API",
+ "wsError": "Error: {{error}}",
+ "websocketError": "WebSocket error",
+ "disconnected": "Disconnected",
+ "connectionFailed": "Connection failed: {{error}}",
+ "listening": "🎙️ Listening...",
+ "microphoneError": "Microphone error: {{error}}",
+ "connected": "Connected",
+ "connecting": "Connecting...",
+ "disconnectedStatus": "Disconnected",
+ "connect": "Connect",
+ "disconnect": "Disconnect",
+ "emptyTitle": "Realtime Voice Playground",
+ "emptyHint": "Click Connect to start a realtime session. You can speak using your microphone or type messages. The AI will respond with voice and text.",
+ "you": "You",
+ "ai": "AI",
+ "stopRecording": "Stop recording",
+ "startRecording": "Start recording",
+ "inputPlaceholder": "Type a message or use the mic...",
+ "listeningHint": "Listening — speak into your microphone. Server VAD will detect when you stop."
+ },
+ "responseMetrics": {
+ "timeToFirstToken": "Time to first token",
+ "totalLatency": "Total latency",
+ "promptTokens": "Prompt tokens",
+ "completionTokens": "Completion tokens",
+ "reasoningTokens": "Reasoning tokens",
+ "totalTokens": "Total tokens",
+ "cost": "Cost",
+ "toolUsed": "Tool used",
+ "ttft": "TTFT: {{value}}s",
+ "totalLatencyValue": "Total Latency: {{value}}s",
+ "in": "In: {{count}}",
+ "out": "Out: {{count}}",
+ "reasoning": "Reasoning: {{count}}",
+ "total": "Total: {{count}}",
+ "toolName": "Tool: {{name}}"
+ },
+ "searchResultsDisplay": {
+ "hideSources": "Hide sources",
+ "showSources": "Show sources ({{count}})",
+ "query": "Query:",
+ "resultCount_one": "{{count}} result",
+ "resultCount_other": "{{count}} results",
+ "metadata": "Metadata:"
+ },
+ "sessionManagement": {
+ "title": "Session Management",
+ "toggleTooltip": "Choose between LiteLLM API session management (using previous_response_id) or UI-based session management (using chat history)",
+ "copiedToClipboard": "Response ID copied to clipboard!",
+ "apiSessionReady": "API Session: Ready",
+ "uiSessionReady": "UI Session: Ready",
+ "responseIdPrefix": "Response ID",
+ "uiSessionPrefix": "UI Session",
+ "apiSessionReadyDesc": "LiteLLM will manage session using previous_response_id",
+ "uiSessionReadyDesc": "UI will manage session using chat history",
+ "apiSessionActiveDesc": "LiteLLM API session active - context maintained server-side",
+ "uiSessionActiveDesc": "UI session active - context maintained client-side",
+ "copyTooltipTitle": "Copy response ID to continue session:"
}
},
"settingsPages": {
@@ -4365,6 +5014,7 @@
"categories": "Categories",
"showingCount": "Showing {{filtered}} of {{total}} templates",
"noTemplatesMatch": "No templates match the selected filters.",
+ "clearAll": "Clear all",
"clearAllFilters": "Clear all filters",
"complexityLabel": "{{complexity}} Complexity",
"inheritsFrom": "Inherits from:",
@@ -4773,6 +5423,7 @@
"colPerRequest": "Per Request",
"colMarginFee": "Margin Fee",
"totalPerRequest": "Total Per Request",
+ "breakdownTotalPerRequest": "Total/Request",
"totalPeriod": "Total {{periodLabel}}",
"marginFeePerRequest": "Margin Fee/Request",
"periodMarginFeeTotal": "{{periodLabel}} Margin Fee",
@@ -5052,5 +5703,178 @@
"tableView": "Table",
"chartView": "Chart"
}
+ },
+ "vectorStoreProviders": {
+ "pgVector": {
+ "apiBaseLabel": "API Base",
+ "apiBaseTooltip": "Enter the base URL of your deployed litellm-pgvector server (e.g., http://your-server:8000)",
+ "apiKeyLabel": "API Key",
+ "apiKeyTooltip": "Enter the API key from your deployed litellm-pgvector server"
+ },
+ "vertexAiSearch": {
+ "vertexProjectLabel": "Vertex Project",
+ "vertexProjectTooltip": "Google Cloud project ID that hosts the Vertex AI Search data store.",
+ "vertexLocationLabel": "Vertex Location",
+ "vertexLocationTooltip": "Vertex AI Search data store location. Must be one of global, us, or eu.",
+ "vertexCollectionIdLabel": "Collection ID (optional)",
+ "vertexCollectionIdTooltip": "Discovery Engine collection ID. Leave blank to use the default collection.",
+ "vertexEngineIdLabel": "Engine ID (optional)",
+ "vertexEngineIdTooltip": "Search app (engine) ID. Required for website, healthcare, and connector-based data stores (Workspace, Slack, Jira, etc.) because these sources route search through an engine. Leave blank to query the data store directly."
+ },
+ "openai": {
+ "apiKeyLabel": "API Key",
+ "apiKeyTooltip": "Enter your OpenAI API key"
+ },
+ "azure": {
+ "apiKeyLabel": "API Key",
+ "apiKeyTooltip": "Enter your Azure OpenAI API key",
+ "apiBaseLabel": "API Base",
+ "apiBaseTooltip": "Enter your Azure OpenAI endpoint (e.g., https://your-resource.openai.azure.com/)"
+ },
+ "milvus": {
+ "apiKeyLabel": "API Key",
+ "apiKeyTooltip": "To obtain a token, you should use a colon (:) to concatenate the username and password that you use to access your Milvus instance (e.g., username:password)",
+ "apiBaseLabel": "API Base",
+ "apiBaseTooltip": "Enter your Milvus endpoint (e.g., https://your-milvus-endpoint.com/)",
+ "embeddingModelLabel": "Embedding Model",
+ "embeddingModelTooltip": "Select the embedding model to use"
+ },
+ "s3Vectors": {
+ "vectorBucketNameLabel": "Vector Bucket Name",
+ "vectorBucketNameTooltip": "S3 bucket name for vector storage (will be auto-created if it doesn't exist)",
+ "indexNameLabel": "Index Name",
+ "indexNameTooltip": "Name for the vector index (optional, will be auto-generated if not provided)",
+ "awsRegionLabel": "AWS Region",
+ "awsRegionTooltip": "AWS region where the S3 bucket is located (e.g., us-west-2)",
+ "embeddingModelLabel": "Embedding Model",
+ "embeddingModelTooltip": "Select the embedding model to use for vector generation"
+ }
+ },
+ "vectorStoreManagement": {
+ "createVectorStore": {
+ "pageTitle": "Create Vector Store",
+ "pageSubtitle": "Upload documents and select a provider to create a new vector store with embedded content.",
+ "step1Title": "Step 1: Upload Documents",
+ "step1Subtitle": "Upload one or more documents (PDF, TXT, DOCX, MD). Maximum file size: 50MB per file.",
+ "draggerText": "Click or drag files to this area to upload",
+ "draggerHint": "Support for single or bulk upload. Supported formats: PDF, TXT, DOCX, MD",
+ "uploadedDocuments": "Uploaded Documents ({{count}})",
+ "step2Title": "Step 2: Configure Vector Store",
+ "step2Subtitle": "Choose the provider and optionally provide a name and description for your vector store.",
+ "vectorStoreNameLabel": "Vector Store Name",
+ "vectorStoreNameTooltip": "Optional: Give your vector store a meaningful name",
+ "vectorStoreNamePlaceholder": "e.g., Product Documentation, Customer Support KB",
+ "descriptionTooltip": "Optional: Describe what this vector store contains",
+ "descriptionPlaceholder": "e.g., Contains all product documentation and user guides",
+ "providerLabel": "Provider",
+ "providerTooltip": "Select the provider for embedding and vector store operations",
+ "unsupportedFileType": "{{name}} is not a supported file type. Please upload PDF, TXT, DOCX, or MD files.",
+ "fileTooLarge": "{{name}} must be smaller than 50MB!",
+ "uploadAtLeastOne": "Please upload at least one document",
+ "selectProvider": "Please select a provider",
+ "provideField": "Please provide {{label}}",
+ "bucketNameMinLength": "Vector bucket name must be at least 3 characters",
+ "indexNameMinLength": "Index name must be at least 3 characters if provided",
+ "createSuccess": "Successfully created vector store with {{count}} document(s). Vector Store ID: {{vectorStoreId}}",
+ "createFailed": "Failed to create vector store: {{error}}",
+ "creating": "Creating Vector Store...",
+ "createButton": "Create Vector Store",
+ "successMessage": "Vector Store Created Successfully",
+ "vectorStoreIdLabel": "Vector Store ID:",
+ "documentsIngestedLabel": "Documents Ingested:"
+ },
+ "documentsTable": {
+ "idCopied": "Document ID copied to clipboard",
+ "statusUploading": "Uploading",
+ "statusReady": "Ready",
+ "statusRemoved": "Removed",
+ "viewDetails": "View details",
+ "copyId": "Copy ID",
+ "emptyText": "No documents uploaded yet. Upload documents above to get started."
+ },
+ "s3VectorsConfig": {
+ "alertTitle": "AWS S3 Vectors Setup",
+ "alertDescription": "AWS S3 Vectors allows you to store and query vector embeddings directly in S3:",
+ "alertItem1": "Vector buckets and indexes will be automatically created if they don't exist",
+ "alertItem2": "Vector dimensions are auto-detected from your selected embedding model",
+ "alertItem3": "Ensure your AWS credentials have permissions for S3 Vectors operations",
+ "alertItem4Prefix": "Learn more:",
+ "alertItem4Link": "AWS S3 Vectors Documentation",
+ "vectorBucketNameLabel": "Vector Bucket Name",
+ "vectorBucketNameTooltip": "S3 bucket name for vector storage (must be at least 3 characters, lowercase letters, numbers, hyphens, and periods only)",
+ "vectorBucketNamePlaceholder": "my-vector-bucket (min 3 chars)",
+ "bucketNameHelp": "Bucket name must be at least 3 characters",
+ "indexNameLabel": "Index Name",
+ "indexNameTooltip": "Name for the vector index (optional, will be auto-generated if not provided). If provided, must be at least 3 characters.",
+ "indexNamePlaceholder": "my-vector-index (optional, min 3 chars)",
+ "indexNameHelp": "Index name must be at least 3 characters if provided",
+ "awsRegionLabel": "AWS Region",
+ "awsRegionTooltip": "AWS region where the S3 bucket is located (e.g., us-west-2)",
+ "embeddingModelLabel": "Embedding Model",
+ "embeddingModelTooltip": "Select the embedding model to use for vector generation",
+ "embeddingModelPlaceholder": "Select an embedding model"
+ },
+ "testVectorStoreTab": {
+ "accessTokenRequired": "Access token is required to test vector stores.",
+ "noVectorStores": "No vector stores available. Create one first to test it.",
+ "selectTitle": "Select Vector Store",
+ "selectSubtitle": "Choose a vector store to test search queries against",
+ "selectPlaceholder": "Select a vector store"
+ },
+ "vectorStoreForm": {
+ "modalTitle": "Add New Vector Store",
+ "providerLabel": "Provider",
+ "providerTooltip": "Select the provider for this vector store",
+ "providerRequired": "Please select a provider",
+ "pgVectorAlertTitle": "PG Vector Setup Required",
+ "pgVectorAlertDescription": "LiteLLM provides a server to connect to PG Vector. To use this provider:",
+ "pgVectorStep1": "Deploy the litellm-pgvector server from:",
+ "pgVectorStep2": "Configure your PostgreSQL database with pgvector extension",
+ "pgVectorStep3": "Start the server and note the API base URL and API key",
+ "pgVectorStep4": "Enter those details in the fields below",
+ "vertexRagAlertTitle": "Vertex AI RAG Engine Setup",
+ "vertexRagAlertDescription": "To use Vertex AI RAG Engine:",
+ "vertexRagStep1": "Set up your Vertex AI RAG Engine corpus following the guide:",
+ "vertexRagStep1Link": "Vertex AI RAG Engine Overview",
+ "vertexRagStep2": "Create a corpus in your Google Cloud project",
+ "vertexRagStep3": "Note the corpus ID from the Vertex AI console",
+ "vertexRagStep4": "Enter the corpus ID in the Vector Store ID field below",
+ "vertexSearchAlertTitle": "Vertex AI Search Setup",
+ "vertexSearchAlertDescription": "To use Vertex AI Search (Discovery Engine):",
+ "vertexSearchStep1": "Enable the Discovery Engine API on your Google Cloud project and create a data store following the guide:",
+ "vertexSearchStep1Link": "Create a Vertex AI Search data store",
+ "vertexSearchStep2": "Pick a supported location: global, us, or eu",
+ "vertexSearchStep3": "For most data store types (Cloud Storage, BigQuery, Media): copy the data store ID and enter it in the Vector Store ID field below.",
+ "vertexSearchStep4": "For website, healthcare, and connector-based sources (Drive, Gmail, Slack, Jira, etc.): create a search app on top of the data store, then copy the Engine ID and enter it in the Engine ID field. The Vector Store ID is still required as the LiteLLM-side name for this record, but it isn't used in the GCP URL when Engine ID is set.",
+ "vectorStoreIdLabel": "Vector Store ID",
+ "vectorStoreIdTooltip": "Enter the vector store ID from your api provider",
+ "vectorStoreIdRequired": "Please input the vector store ID from your api provider",
+ "vectorStoreIdPlaceholderVertexRag": "6917529027641081856 (Get corpus ID from Vertex AI console)",
+ "vectorStoreIdPlaceholderVertexSearch": "my-datastore_1234567890 (Get data store ID from Vertex AI Search console)",
+ "vectorStoreIdPlaceholderVertexSearchEngine": "Any identifier you'll use to reference this in LiteLLM",
+ "vectorStoreIdPlaceholderDefault": "Enter vector store ID from your provider",
+ "fieldSelectRequired": "Please select the {{label}}",
+ "fieldInputRequired": "Please input the {{label}}",
+ "vectorStoreNameLabel": "Vector Store Name",
+ "vectorStoreNameTooltip": "Custom name you want to give to the vector store, this name will be rendered on the LiteLLM UI",
+ "existingCredentialsLabel": "Existing Credentials",
+ "existingCredentialsTooltip": "Optionally select API provider credentials for this vector store eg. Bedrock API KEY",
+ "existingCredentialsPlaceholder": "Select or search for existing credentials",
+ "metadataLabel": "Metadata",
+ "metadataTooltip": "JSON metadata for the vector store (optional)",
+ "invalidMetadataJson": "Invalid JSON in metadata field",
+ "createSuccess": "Vector store created successfully",
+ "createFailed": "Error creating vector store: {{error}}"
+ },
+ "vectorStoreTable": {
+ "colVectorStoreId": "Vector Store ID",
+ "colFiles": "Files",
+ "colProvider": "Provider",
+ "oneFile": "1 file",
+ "nFiles": "{{count}} files",
+ "editTooltip": "Edit vector store",
+ "deleteTooltip": "Delete vector store",
+ "noVectorStores": "No vector stores found"
+ }
}
}
diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json
index 110a88b8272..04c0bb10299 100644
--- a/ui/litellm-dashboard/src/locales/zh-CN.json
+++ b/ui/litellm-dashboard/src/locales/zh-CN.json
@@ -1590,6 +1590,258 @@
"updateSuccess": "护栏已成功更新",
"updateFailed": "更新护栏失败",
"notFound": "未找到护栏"
+ },
+ "teamGuardrailsTab": {
+ "statusActive": "已激活",
+ "statusPendingReview": "待审核",
+ "statusRejected": "已拒绝",
+ "teamLabel": "团队:{{team}}",
+ "modelLabel": "模型:",
+ "submittedLabel": "提交时间:",
+ "forwardApiKey": "转发 API 密钥",
+ "review": "审阅",
+ "approve": "批准",
+ "reject": "拒绝",
+ "staticHeaders": "静态请求头",
+ "noStaticHeaders": "未配置静态请求头。",
+ "submittedBy": "由 {{by}} 于 {{at}} 提交",
+ "closeDetailPanel": "关闭详情面板",
+ "endpoint": "端点",
+ "method": "方法",
+ "forwardLiteLLMApiKey": "转发 LiteLLM API 密钥",
+ "forwardKeyDesc": "启用后,调用方的 LiteLLM API 密钥将作为 Authorization 请求头转发到您的护栏端点,使护栏能够使用原始调用方凭据验证模型调用。",
+ "staticHeadersDesc": "随每次护栏请求一同发送。",
+ "removeHeader": "移除 {{name}}",
+ "headerNamePlaceholder": "请求头名称(如 X-API-Key)",
+ "headerValuePlaceholder": "值",
+ "forwardClientHeaders": "转发客户端请求头",
+ "forwardClientHeadersDesc": "允许从客户端请求转发到护栏的请求头名称(如 x-request-id)。",
+ "noForwardClientHeaders": "未配置转发客户端请求头。",
+ "extraHeaderPlaceholder": "如 x-request-id",
+ "equivalentConfig": "等效配置",
+ "guardrailInfoNote": "此护栏运行在独立实例上,接收用户请求并将结果转发到流水线下一步。请参阅 LiteLLM Generic Guardrail API 文档 了解配置详情。",
+ "testEndpoint": "测试端点",
+ "approveGuardrailTitle": "批准护栏",
+ "rejectGuardrailTitle": "拒绝护栏",
+ "approveGuardrailConfirm": "确定要批准「{{name}}」吗?批准后将使其激活并可供使用。",
+ "rejectGuardrailConfirm": "确定要拒绝「{{name}}」吗?拒绝后将标记为已拒绝并通知团队。",
+ "totalSubmitted": "已提交总数",
+ "searchPlaceholder": "搜索护栏...",
+ "filterAllStatus": "所有状态",
+ "addGuardrail": "添加护栏",
+ "loadingSubmissions": "加载提交记录中…",
+ "noGuardrailsMatch": "没有护栏匹配您的筛选条件。",
+ "failedToLoadSubmissions": "加载提交记录失败",
+ "forwardApiKeyEnabled": "转发 API 密钥已启用",
+ "forwardApiKeyDisabled": "转发 API 密钥已禁用",
+ "failedToUpdateForwardApiKey": "更新转发 API 密钥失败",
+ "staticHeadersUpdated": "静态请求头已更新",
+ "failedToUpdateStaticHeaders": "更新静态请求头失败",
+ "forwardClientHeadersUpdated": "转发客户端请求头已更新",
+ "failedToUpdateForwardClientHeaders": "更新转发客户端请求头失败",
+ "guardrailApproved": "护栏已批准",
+ "failedToApproveGuardrail": "批准护栏失败",
+ "guardrailRejected": "护栏已拒绝",
+ "failedToRejectGuardrail": "拒绝护栏失败",
+ "submitModalTitle": "提交护栏审核",
+ "submitForReview": "提交审核",
+ "submitCallout": "您的护栏将在激活前发送给管理员审核。",
+ "guardrailSubmitted": "护栏已提交审核",
+ "formTeam": "团队",
+ "formTeamRequired": "请选择团队",
+ "formGuardrailName": "护栏名称",
+ "formGuardrailNameRequired": "请输入护栏名称",
+ "formGuardrailNamePlaceholder": "如 pii-detection",
+ "formMode": "模式",
+ "formModeRequired": "请选择模式",
+ "modePreCall": "调用前",
+ "modePostCall": "调用后",
+ "modeDuringCall": "调用中",
+ "formApiBaseUrl": "API 基础 URL",
+ "formApiBaseUrlRequired": "请输入 API 基础 URL",
+ "formApiBaseUrlInvalid": "请输入有效的 URL",
+ "formApiBaseUrlPlaceholder": "https://your-guardrail-api.com/v1/check",
+ "formExtraParams": "附加 litellm_params(可选)",
+ "formExtraParamsTooltip": "合并到 litellm_params 的 JSON 对象,如 forward_api_key、headers、model、unreachable_fallback",
+ "formExtraParamsPlaceholder": "{\"forward_api_key\": true, \"headers\": {\"X-Custom\": \"value\"}}",
+ "formMustBeJsonObject": "必须为 JSON 对象",
+ "formInvalidJson": "JSON 格式无效",
+ "formGuardrailInfo": "护栏信息(可选)",
+ "formGuardrailInfoPlaceholder": "{\"description\": \"Detects PII in requests\"}"
+ },
+ "guardrailGardenTab": "护栏库",
+ "guardrailsTab": "护栏",
+ "testPlaygroundTab": "测试 Playground",
+ "submittedGuardrailsTab": "已提交的护栏",
+ "addNewGuardrail": "+ 添加新护栏",
+ "addProviderGuardrail": "添加提供商护栏",
+ "createCustomCodeGuardrail": "创建自定义代码护栏",
+ "deleteGuardrailTitle": "删除护栏",
+ "deleteGuardrailMessage": "确定要删除护栏:{{name}}?此操作无法撤销。",
+ "guardrailInfoTitle": "护栏信息",
+ "labelId": "ID",
+ "labelMode": "模式",
+ "labelDefaultOn": "默认启用",
+ "deleteSuccess": "护栏「{{name}}」已成功删除",
+ "deleteFailed": "删除护栏失败",
+ "addGuardrailForm": {
+ "modalTitle": "创建护栏",
+ "guardrailNameLabel": "护栏名称",
+ "guardrailNameRequired": "请输入护栏名称",
+ "guardrailNamePlaceholder": "为此护栏输入名称",
+ "providerLabel": "护栏提供商",
+ "providerRequired": "请选择提供商",
+ "providerPlaceholder": "选择护栏提供商",
+ "modeLabel": "模式",
+ "modeTooltip": "护栏的应用方式",
+ "modeRequired": "请选择模式",
+ "recommended": "推荐",
+ "alwaysOnLabel": "始终启用",
+ "alwaysOnTooltip": "启用后,此护栏将默认应用于所有请求。",
+ "skipSystemMsgLabel": "在护栏中跳过系统消息",
+ "skipSystemMsgTooltip": "仅限统一护栏:从护栏评估输入中省略 role: system(OpenAI chat + Anthropic messages)。模型仍接收完整消息。使用全局默认则遵循 litellm_settings.skip_system_message_in_guardrail。",
+ "skipToolMsgLabel": "在护栏中跳过工具消息",
+ "skipToolMsgTooltip": "仅限统一护栏:从护栏评估输入中省略 role: tool(OpenAI chat + Anthropic messages)。模型仍接收完整消息。使用全局默认则遵循 litellm_settings.skip_tool_message_in_guardrail。",
+ "useGlobalDefault": "使用全局默认",
+ "yesExcludeFromScan": "是 — 从护栏扫描中排除",
+ "noAlwaysInclude": "否 — 始终包含在扫描中",
+ "modeDesc": {
+ "pre_call": "LLM 调用前 - 在 LLM 调用前运行并检查输入(推荐)",
+ "during_call": "LLM 调用中 - 与 LLM 调用并行运行,响应等待检查完成后才返回",
+ "post_call": "LLM 调用后 - 在 LLM 调用后运行,仅检查输出",
+ "logging_only": "仅日志 - 仅在日志回调中运行,不影响 LLM 调用",
+ "pre_mcp_call": "MCP 工具调用前 - 在 MCP 工具执行前运行并验证工具调用",
+ "during_mcp_call": "MCP 工具调用中 - 与 MCP 工具执行并行运行用于监控"
+ },
+ "stepBasicInfo": "基本信息",
+ "stepTopics": "主题",
+ "stepPatterns": "模式",
+ "stepKeywords": "关键词",
+ "stepEndpointSettings": "端点设置(可选)",
+ "stepPiiConfig": "PII 配置",
+ "stepProviderConfig": "提供商配置",
+ "skip": "跳过",
+ "addAndContinue": "添加并继续 →",
+ "continueArrow": "继续 →",
+ "createGuardrailButton": "创建护栏",
+ "endpointSettingsDesc": "为特定调用类型配置设置。大多数护栏不需要此项 — 除非您使用特定端点(如 /v1/realtime),否则请跳过。",
+ "callTypeLabel": "调用类型",
+ "callTypePlaceholder": "选择调用类型",
+ "moreCallTypesSoon": "更多调用类型即将推出。",
+ "realtimeSettingsTitle": "/v1/realtime 设置",
+ "endSessionLabel": "在 X 次违规后结束会话",
+ "endSessionDesc": "在达到指定护栏违规次数后自动关闭会话。留空则永不自动关闭。",
+ "onViolationLabel": "违规时",
+ "violationWarn": "警告",
+ "violationEndSession": "结束会话",
+ "violationWarnDesc": "机器人播报消息,会话继续",
+ "violationEndSessionDesc": "机器人播报消息,连接立即关闭",
+ "violationMessageLabel": "用户听到的消息",
+ "violationMessageDesc": "护栏触发时机器人播报的内容。若留空则回退到默认违规消息。",
+ "violationMessagePlaceholder": "例如:我无法继续此对话。请拨打 1-800-774-2678 联系我们。",
+ "failedToLoadConfig": "加载护栏配置失败",
+ "selectAtLeastOnePii": "请至少选择一个 PII 实体后继续",
+ "configureAtLeastOneFilter": "请至少配置一项内容过滤设置(类别、模式、关键词或竞争对手意图)",
+ "invalidJsonConfig": "配置中的 JSON 格式无效",
+ "addAtLeastOneCriterion": "请至少添加一条评估标准",
+ "weightsMustSum100": "标准权重之和必须为 100%(当前为 {{weightTotal}}%)",
+ "addAtLeastOneRule": "请至少添加一条工具权限规则",
+ "createSuccess": "护栏创建成功",
+ "createFailed": "创建护栏失败:{{error}}"
+ },
+ "guardrailOptionalParams": {
+ "title": "可选参数",
+ "defaultDescription": "为此护栏提供商配置附加设置",
+ "enterValue": "输入 {{key}} 的值",
+ "selectValue": "选择 {{key}} 的值",
+ "selectCategoryPlaceholder": "选择要配置的类别",
+ "selectCategoryHint": "选择类别以添加阈值配置",
+ "fieldRequired": "{{fieldKey}} 为必填项"
+ },
+ "guardrailProviderFields": {
+ "loadFailed": "加载提供商参数失败",
+ "loadingTip": "正在加载提供商参数...",
+ "noFields": "此提供商暂无可配置字段。",
+ "fieldRequired": "{{fieldKey}} 为必填项"
+ },
+ "guardrailTable": {
+ "colGuardrailId": "护栏 ID",
+ "colName": "名称",
+ "colProvider": "提供商",
+ "colMode": "模式",
+ "colDefaultOn": "默认启用",
+ "defaultOn": "默认启用",
+ "defaultOff": "默认关闭",
+ "deleteTooltip": "删除护栏",
+ "configDeleteTooltip": "配置文件中的护栏无法在仪表盘上删除,请从配置文件中删除。",
+ "configDeleteAriaLabel": "删除护栏(配置文件)",
+ "unnamedGuardrail": "未命名护栏",
+ "noGuardrails": "未找到护栏"
+ },
+ "lLMJudgeFields": {
+ "description": "每次 LLM 响应后,Judge Model 会根据您的标准对其评分(0–100)。若加权平均分低于阈值,响应将被拦截(或记录)。",
+ "judgeModelLabel": "Judge Model",
+ "judgeModelTooltip": "读取每条响应并评分的 LLM。请选择能力较强的模型——它仅能看到 LLM 返回的内容,不会接触最终用户数据。",
+ "judgeModelRequired": "请选择 Judge Model",
+ "judgeModelPlaceholder": "选择模型",
+ "minScoreLabel": "最低通过分数",
+ "minScoreTooltip": "0–100。若标准分数的加权平均值低于此值,护栏将触发。建议默认值为 80。",
+ "onFailureLabel": "失败时的处理",
+ "onFailureTooltip": "拦截:分数过低时返回 HTTP 422。仅记录:记录结果但允许响应通过。",
+ "onFailureBlock": "拦截(返回 422)",
+ "onFailureLog": "仅记录",
+ "criteriaLabel": "评估标准",
+ "criteriaTooltip": "每个标准是 Judge 需要检查的一项内容,权重之和必须为 100%。",
+ "criterionNameRequired": "请输入标准名称",
+ "criterionNamePlaceholder": "标准名称(例如:策略准确性)",
+ "weightLabel": "权重",
+ "weightTooltip": "此标准在最终分数中所占的比重,所有权重之和必须为 100%。",
+ "weightRequired": "请输入权重",
+ "criterionDescRequired": "请描述要检查的内容",
+ "criterionDescPlaceholder": "Judge 应针对此标准检查什么?",
+ "addCriterion": "添加标准",
+ "weightsTotal": "权重合计:{{weightTotal}}%",
+ "weightsMustSum": "必须合计为 100%"
+ },
+ "piiComponents": {
+ "filterByCategory": "按类别筛选",
+ "selectCategoriesPlaceholder": "选择要筛选的类别",
+ "quickActions": "快速操作",
+ "quickActionsTooltip": "一次性对所有 PII 类型应用操作",
+ "unselectAll": "取消全选",
+ "selectAllMask": "全选并脱敏",
+ "selectAllBlock": "全选并拦截",
+ "piiTypeHeader": "PII 类型",
+ "actionHeader": "操作",
+ "noMatch": "没有 PII 类型匹配您的筛选条件"
+ },
+ "piiConfiguration": {
+ "title": "配置 PII 保护",
+ "itemsSelected_one": "已选择 {{count}} 项",
+ "itemsSelected_other": "已选择 {{count}} 项"
+ },
+ "toolPermissionRulesEditor": {
+ "title": "LiteLLM 工具权限护栏",
+ "subtitle": "为工具名称或类型提供正则表达式模式(例如 ^mcp__github_.*$),并可选择性地约束载荷字段。",
+ "addRule": "添加规则",
+ "noRules": "尚未添加工具规则",
+ "ruleLabel": "规则 {{index}}",
+ "ruleId": "规则 ID",
+ "toolName": "工具名称(可选)",
+ "toolType": "工具类型(可选)",
+ "decision": "决策",
+ "allow": "允许",
+ "deny": "拒绝",
+ "restrictArgs": "+ 限制工具参数(可选)",
+ "argConstraints": "参数约束(点路径或数组路径)",
+ "addConstraint": "+ 添加另一个约束",
+ "defaultAction": "默认动作",
+ "onDisallowedAction": "禁止时的处理",
+ "onDisallowedTooltip": "拦截:调用被禁止工具时返回错误。改写:去除工具调用但允许响应的其余部分继续。",
+ "block": "拦截",
+ "rewrite": "改写",
+ "violationMessage": "违规消息(可选)",
+ "violationMessagePlaceholder": "这违反了我们的组织策略..."
}
},
"keyValueInput": {
@@ -2662,7 +2914,113 @@
"collapseRow": "折叠行",
"hideJson": "隐藏 JSON",
"showJson": "显示 JSON",
- "copied": "已复制!"
+ "copied": "已复制!",
+ "colAction": "操作",
+ "colChangedBy": "变更人"
+ },
+ "auditLogDrawer": {
+ "tableKeys": "密钥",
+ "tableTeams": "团队",
+ "tableUsers": "用户",
+ "tableOrganizations": "组织",
+ "tableModels": "模型",
+ "copyJson": "复制 JSON",
+ "noDifferingFields": "未检测到差异字段",
+ "tokenLabel": "Token:",
+ "spendLabel": "花费:",
+ "maxBudgetLabel": "最大预算:",
+ "before": "变更前",
+ "after": "变更后",
+ "labelTable": "表",
+ "labelObjectId": "对象 ID",
+ "labelChangedBy": "操作人",
+ "labelApiKeyHash": "API 密钥(哈希)"
+ },
+ "configInfoMessage": {
+ "title": "请求/响应数据不可用",
+ "description": "要查看请求和响应详情,请在您的 LiteLLM 配置中启用提示词存储,方法是在 proxy_config.yaml 文件中添加以下内容,或在管理员设置 → 日志设置 中切换该选项。",
+ "note": "注意:此设置仅对配置更改后的新请求生效。"
+ },
+ "costBreakdownViewer": {
+ "title": "费用明细",
+ "cached": "已缓存",
+ "inputCost": "输入费用",
+ "outputCost": "输出费用",
+ "cacheReadCost": "缓存读取费用",
+ "cacheWriteCost": "缓存写入费用",
+ "toolUsageCost": "工具使用费用",
+ "tokens": "Token",
+ "promptTokens": "提示词 Token",
+ "completionTokens": "补全 Token",
+ "originalLlmCost": "原始 LLM 费用",
+ "discount": "折扣",
+ "discountAmount": "折扣金额",
+ "margin": "利润",
+ "finalCalculatedCost": "最终计算费用"
+ },
+ "errorViewer": {
+ "title": "错误详情",
+ "type": "类型",
+ "message": "消息",
+ "unknownError": "未知错误",
+ "unknownErrorOccurred": "发生了未知错误",
+ "traceback": "堆栈跟踪",
+ "collapseAll": "全部折叠",
+ "expandAll": "全部展开",
+ "copyTraceback": "复制堆栈跟踪"
+ },
+ "evalViewer": {
+ "title": "LLM 评判结果",
+ "colCriterion": "标准",
+ "colWeight": "权重",
+ "colScore": "得分",
+ "colWeighted": "加权得分",
+ "weightedTooltip": "得分 × 权重 — 每个标准对最终得分的贡献度",
+ "colComment": "备注",
+ "passed": "通过",
+ "failed": "未通过",
+ "overallScoreTooltip": "所有标准得分的加权平均值。每个标准在创建评估时设置权重(%),权重越高的标准对最终得分影响越大。",
+ "threshold": "阈值",
+ "judge": "评判模型",
+ "iter": "迭代",
+ "judgeError": "评判错误",
+ "scoreNoCriterion": "得分:{{score}} — 无逐标准明细。"
+ },
+ "bedrockGuardrailDetails": {
+ "detected": "已检测",
+ "notDetected": "未检测",
+ "textGuarded": "文本已守护 {{guarded}}/{{total}}",
+ "imagesGuarded": "图片已守护 {{guarded}}/{{total}}",
+ "action": "动作",
+ "actionReason": "动作原因",
+ "blockedResponse": "已拦截响应",
+ "coverage": "覆盖范围",
+ "usage": "用量",
+ "outputs": "输出",
+ "nonTextOutput": "(非文本输出)",
+ "assessmentTitle": "评估 #{{number}}",
+ "wordPolicy": "词语策略",
+ "customWords": "自定义词语",
+ "managedWordLists": "托管词语列表",
+ "contentPolicy": "内容策略",
+ "colType": "类型",
+ "colAction": "动作",
+ "colDetected": "是否检测到",
+ "colStrength": "强度",
+ "colConfidence": "置信度",
+ "contextualGrounding": "上下文接地",
+ "colScore": "得分",
+ "colThreshold": "阈值",
+ "sensitiveInformation": "敏感信息",
+ "piiEntities": "PII 实体",
+ "customRegexes": "自定义正则",
+ "topicPolicy": "主题策略",
+ "invocationMetrics": "调用指标",
+ "latencyMs": "延迟(毫秒)",
+ "textCoverage": "文本 {{guarded}}/{{total}}",
+ "imagesCoverage": "图片 {{guarded}}/{{total}}",
+ "automatedReasoningFindings": "自动推理发现",
+ "rawResponse": "原始 Bedrock 护栏响应"
}
},
"userAgentActivity": {
@@ -3278,7 +3636,7 @@
"invalidJsonStdioEnv": "stdio 环境变量配置中的 JSON 无效",
"stdioRequiresCommand": "stdio 传输需要一个命令",
"invalidJsonTokenValidation": "Token 验证规则中的 JSON 无效",
- "oauthTokenPersistFailed": "MCP 服务器已更新,但 OAuth Token 持久化失败{{message}}",
+ "oauthTokenPersistFailed": "MCP 服务器已更新,但 OAuth Token 持久化失败:{{message}}",
"updateSuccess": "MCP 服务器更新成功",
"updateFailed": "MCP 服务器更新失败{{message}}",
"tabServerConfig": "服务器配置",
@@ -3541,6 +3899,297 @@
"verdictGap": "缺口 — 本应被拦截",
"verdictFalsePositive": "误报 — 被错误拦截",
"llmResponse": "模型响应:"
+ },
+ "a2AMetrics": {
+ "header": "A2A 元数据",
+ "totalLatency": "总延迟",
+ "timeToFirstToken": "首 Token 时间",
+ "clickToCopy": "点击复制:{{id}}",
+ "taskPrefix": "任务:",
+ "sessionPrefix": "会话:",
+ "details": "详情",
+ "statusMessage": "状态消息:",
+ "taskId": "任务 ID:",
+ "sessionId": "会话 ID:",
+ "customMetadata": "自定义元数据:"
+ },
+ "additionalModelSettings": {
+ "useAdvancedParams": "使用高级参数",
+ "simulateFailure": "模拟失败以测试回退",
+ "simulateFailureDesc": "使第一个请求失败,以便路由器尝试回退(如已配置)。用于验证您的回退设置。",
+ "simulateFailureNote": "当配置了密钥、团队或路由器设置时,行为可能有所不同。了解更多 ",
+ "simulateFailureAriaLabel": "帮助:模拟失败以测试回退",
+ "temperature": "Temperature",
+ "temperatureTooltip": "控制随机性。值越低输出越确定,值越高输出越有创意。",
+ "maxTokens": "最大 Token 数",
+ "maxTokensTooltip": "响应中生成的最大 Token 数。"
+ },
+ "agentBuilderView": {
+ "title": "Agent Builder",
+ "saveAgent": "保存 Agent",
+ "buildAgentsSubtitle": "构建符合合规要求的 Agent。",
+ "experimentalBanner": "Agent Builder 为实验性功能,可能随时更改或移除。欢迎反馈——请发送邮件至 product@berri.ai 。",
+ "agentsLabel": "Agents",
+ "addAgentAriaLabel": "添加 Agent",
+ "newAgent": "新建 Agent",
+ "noAgentsYet": "暂无 Agent。添加一个 Agent 以开始使用。",
+ "signInRequired": "请登录以使用 Agent Builder。",
+ "tabConfigure": "配置",
+ "tabChat": "聊天",
+ "tabBatchTest": "批量测试",
+ "tabConnect": "连接",
+ "missingModelIdWarning": "此 Agent 无法在此处更新或删除(缺少模型 ID)。请从模型与端点页面管理。",
+ "agentNameLabel": "Agent 名称",
+ "agentNamePlaceholder": "我的 Agent",
+ "systemPromptLabel": "系统提示词",
+ "systemPromptPlaceholder": "你是一个有帮助的助手...",
+ "defaultSystemPrompt": "You are a helpful assistant.",
+ "underlyingLlmLabel": "底层 LLM",
+ "temperatureLabel": "Temperature",
+ "maxTokensLabel": "最大 Token 数",
+ "mcpServersLabel": "MCP 服务器",
+ "mcpServersPlaceholder": "选择要附加的 MCP 服务器(格式与 chat completions API 相同)",
+ "mcpServersSaved_one": "已保存 {{count}} 个 MCP 服务器。调用此 Agent 时,请在 chat completions 中使用相同的 tools 数组。",
+ "mcpServersSaved_other": "已保存 {{count}} 个 MCP 服务器。调用此 Agent 时,请在 chat completions 中使用相同的 tools 数组。",
+ "updateAgent": "更新 Agent",
+ "testInChat": "在聊天中测试",
+ "saveAgentFirst": "请先保存 Agent 以在聊天中测试。",
+ "selectAgentForBatchTest": "请选择一个 Agent 以运行批量测试。",
+ "selectAgentToConnect": "请选择一个 Agent 以查看连接方式。",
+ "proxyBaseUrl": "代理基础 URL",
+ "callYourAgent": "调用您的 Agent(cURL)",
+ "createKeyTitle": "为此 Agent 创建密钥",
+ "createKeyDesc": "创建一个只能调用此 Agent 的虚拟密钥。该密钥将绑定到您(user_id),并限制为模型 {{agentName}} 。",
+ "createKeyButton": "为此 Agent 创建密钥",
+ "keyCreationDisabled": "您的账户已禁用密钥创建。",
+ "keyCreated": "密钥已创建。它显示在上方的 cURL 示例中——复制代码片段以使用。",
+ "failedToLoadAgents": "加载 Agent 失败",
+ "nameAndModelRequired": "名称和底层模型为必填项",
+ "failedToSaveAgent": "保存 Agent 失败",
+ "agentUpdated": "Agent 已成功更新",
+ "failedToUpdateAgent": "更新 Agent 失败",
+ "virtualKeyCreated": "虚拟密钥已创建。请在下方的 curl 示例中使用。",
+ "keyCreatedNoValue": "密钥已创建但未返回值",
+ "failedToCreateKey": "为 Agent 创建密钥失败",
+ "deleteAgentTitle": "删除 Agent",
+ "deleteAgentConfirm": "确定要删除 \"{{name}}\"?此操作无法撤销。",
+ "agentDeleted": "Agent 已删除",
+ "failedToDeleteAgent": "删除 Agent 失败"
+ },
+ "audioRenderer": {
+ "browserNotSupported": "您的浏览器不支持音频元素。"
+ },
+ "chatImageRenderer": {
+ "uploadedImageAlt": "用户上传的图片"
+ },
+ "chatImageUpload": {
+ "attachTooltip": "附加图片或 PDF"
+ },
+ "chatMessageBubble": {
+ "generatedImageAlt": "生成的图片"
+ },
+ "chatUi": {
+ "requestCancelled": "请求已取消",
+ "pleaseUploadImage": "请至少上传一张图片用于编辑",
+ "pleaseUploadAudio": "请上传一个音频文件用于转录",
+ "pleaseSelectAgent": "请选择一个 Agent 以发送消息",
+ "pleaseSelectMCPServer": "请选择一个 MCP 服务器进行测试",
+ "pleaseSelectMCPTool": "请选择一个 MCP 工具进行调用",
+ "waitForToolSchema": "请等待工具 schema 加载完成",
+ "fillRequiredParameters": "请填写所有必填参数",
+ "pleaseSelectModel": "请在发送请求前选择一个模型",
+ "pleaseProvideVirtualKey": "请提供虚拟密钥或选择当前 UI 会话",
+ "failedToProcessImage": "处理图片失败,请重试。",
+ "toolExecutedSuccessfully": "工具执行成功。",
+ "errorFetchingResponse": "获取响应时出错:{{error}}",
+ "chatHistoryCleared": "聊天记录已清除。",
+ "accessDenied": "拒绝访问",
+ "askProxyAdminForAccess": "请联系代理管理员以获取测试模型的权限",
+ "configurations": "配置",
+ "virtualKeySource": "虚拟密钥来源",
+ "currentUiSession": "当前 UI 会话",
+ "virtualKeyLabel": "虚拟密钥",
+ "enterCustomVirtualKey": "输入自定义虚拟密钥",
+ "customProxyBaseUrl": "自定义代理基础 URL",
+ "fill": "填入",
+ "customProxyUrlPlaceholder": "可选:输入自定义代理 URL(例如:http://localhost:5000)",
+ "apiCallsSentTo": "API 请求将发送至:{{url}}",
+ "endpointTypeLabel": "端点类型",
+ "voiceLabel": "语音",
+ "selectModelLabel": "选择模型",
+ "advancedParamsTooltip": "高级参数目前仅支持聊天模型",
+ "modelSettings": "模型设置",
+ "selectModelPlaceholder": "选择模型",
+ "enterCustomModel": "输入自定义模型",
+ "enterCustomModelName": "输入自定义模型名称",
+ "selectAgentLabel": "选择 Agent",
+ "selectAgentPlaceholder": "选择一个 Agent",
+ "noAgentsFound": "未找到 Agent。请通过 /v1/agents 端点创建 Agent。",
+ "tagsLabel": "标签",
+ "mcpServerLabel": "MCP 服务器",
+ "mcpServersLabel": "MCP 服务器",
+ "mcpServerTooltipDirect": "选择一个 MCP 服务器或工具集以直接测试工具。",
+ "mcpServerTooltip": "选择 MCP 服务器或工具集以在对话中使用。",
+ "selectMCPServerPlaceholder": "选择 MCP 服务器",
+ "selectMCPServersPlaceholder": "选择 MCP 服务器",
+ "allMCPServers": "所有 MCP 服务器",
+ "useAllMCPServers": "使用所有可用的 MCP 服务器",
+ "toolsetsGroup": "工具集",
+ "toolsetBadge": "工具集",
+ "toolCount": "({{count}} 个工具)",
+ "serversGroup": "服务器",
+ "selectToolLabel": "选择工具",
+ "selectToolPlaceholder": "选择要调用的工具",
+ "limitToolsFor": "限制 {{serverName}} 的工具:",
+ "allToolsDefault": "所有工具(默认)",
+ "serverRequiresApiKey": "{{serverName}} 需要您的 API 密钥",
+ "connected": "已连接",
+ "reconnect": "重新连接",
+ "connectButton": "连接",
+ "vectorStoreLabel": "向量存储",
+ "vectorStoreTooltip": "选择此次 LLM API 调用使用的向量存储。您可以在此处 设置您的向量存储。",
+ "guardrailsLabel": "护栏",
+ "guardrailsTooltip": "选择此次 LLM API 调用使用的护栏。您可以在此处 设置您的护栏。",
+ "policiesLabel": "策略",
+ "policiesTooltip": "选择应用于此次 LLM API 调用的策略。策略根据条件定义要应用的护栏。您可以在此处 设置您的策略。",
+ "testKeyTitle": "测试密钥",
+ "chatTitle": "聊天",
+ "clearChat": "清除聊天",
+ "getCode": "获取代码",
+ "emptyStateHint": "开始对话、生成图片或处理音频",
+ "assistant": "助手",
+ "dragImagesToUpload": "点击或拖拽图片到此处上传",
+ "imageUploadHint": "支持 PNG、JPG、JPEG 格式,可上传多张图片。",
+ "uploadPreviewAlt": "上传预览 {{index}}",
+ "addMore": "添加更多",
+ "dragAudioToUpload": "点击或拖拽音频文件到此处上传",
+ "audioUploadHint": "支持 MP3、MP4、MPEG、MPGA、M4A、WAV、WEBM 格式,最大文件大小:25 MB。",
+ "removeButton": "移除",
+ "runningPythonCode": "正在运行 Python 代码...",
+ "codeInterpreterActive": "代码解释器已激活",
+ "disableButton": "禁用",
+ "samplePrompt1": "生成示例销售数据 CSV 并创建图表",
+ "samplePrompt2": "创建一个对比 AI 网关提供商(包括 LiteLLM)的 PNG 柱状图",
+ "samplePrompt3": "生成 LLM 定价数据的 CSV 并将其可视化为折线图",
+ "suggestPromptA2A1": "你能帮我做什么?",
+ "suggestPromptA2A2": "介绍一下你自己",
+ "suggestPromptA2A3": "你能执行哪些任务?",
+ "suggestPrompt1": "给我写一首诗",
+ "suggestPrompt2": "解释量子计算",
+ "suggestPrompt3": "起草一封礼貌地请求会议的邮件",
+ "codeInterpreterEnabledTooltip": "代码解释器已启用(点击可禁用)",
+ "enableCodeInterpreterTooltip": "启用代码解释器",
+ "codeInterpreterEnabledNotice": "代码解释器已启用!",
+ "placeholderChat": "输入消息...(Shift+Enter 换行)",
+ "placeholderA2A": "向 A2A Agent 发送消息...",
+ "placeholderImageEdits": "描述您希望如何编辑图片...",
+ "placeholderSpeech": "输入要转换为语音的文本...",
+ "placeholderTranscription": "可选:为转录添加上下文或提示词...",
+ "placeholderImage": "描述您想要生成的图片...",
+ "loadingToolSchema": "正在加载工具 schema...",
+ "generatedCodeTitle": "生成的代码",
+ "sdkTypeLabel": "SDK 类型",
+ "openAiSdk": "OpenAI SDK",
+ "azureSdk": "Azure SDK",
+ "copyToClipboard": "复制到剪贴板",
+ "toolsetsInfoTitle": "工具集的工作原理",
+ "toolsetsInfoIntro": "工具集 是来自一个或多个 MCP 服务器的特定工具的命名集合。工具集不会暴露服务器的所有工具,而是为 Agent 提供恰好所需的工具。",
+ "toolsetsHowToUseTitle": "如何使用工具集:",
+ "toolsetsStep1": "从 MCP 服务器下拉列表中选择一个工具集 (紫色标签)。",
+ "toolsetsStep2": "工具选择器将只显示该工具集包含的工具。",
+ "toolsetsStep3": "选择工具并填写其参数,然后发送。",
+ "toolsetsStep4": "工具调用会自动路由到正确的底层 MCP 服务器。",
+ "toolsetsExample": "示例: 一个「GitHub 只读」工具集可能只包含来自 GitHub MCP 服务器的 list_repos 和 get_file——防止 Agent 进行写操作。",
+ "toolsetsCreatingTitle": "创建工具集:",
+ "toolsetsCreatingDesc": "管理员可以从 MCP 页面 → 工具集 标签页创建和管理工具集。工具集随后可分配给密钥和团队以限定其工具访问范围。"
+ },
+ "codeInterpreterOutput": {
+ "pythonCodeExecuted": "已执行的 Python 代码",
+ "loadingImage": "图片加载中...",
+ "generatedChart": "生成的图表",
+ "imageNotAvailable": "图片不可用"
+ },
+ "codeInterpreterTool": {
+ "title": "代码解释器",
+ "tooltipDesc": "运行 Python 代码以生成文件、图表并分析数据。容器将自动创建。",
+ "onlyOpenAIWarning": "代码解释器仅适用于 OpenAI 模型",
+ "onlyOpenAINotice": "代码解释器目前仅支持 OpenAI 模型。",
+ "requestSupportLink": "申请支持其他提供商"
+ },
+ "filePreviewCard": {
+ "uploadPreview": "上传预览",
+ "pdf": "PDF",
+ "image": "图片"
+ },
+ "mcpEventsDisplay": {
+ "listTools": "列出工具",
+ "toolCall": "工具调用",
+ "request": "请求",
+ "approved": "已批准",
+ "response": "响应"
+ },
+ "realtimePlayground": {
+ "title": "实时语音对话",
+ "selectModelFirst": "请先选择一个模型",
+ "connectedToApi": "已连接到实时 API",
+ "wsError": "错误:{{error}}",
+ "websocketError": "WebSocket 错误",
+ "disconnected": "已断开",
+ "connectionFailed": "连接失败:{{error}}",
+ "listening": "🎙️ 正在监听...",
+ "microphoneError": "麦克风错误:{{error}}",
+ "connected": "已连接",
+ "connecting": "连接中...",
+ "disconnectedStatus": "已断开",
+ "connect": "连接",
+ "disconnect": "断开",
+ "emptyTitle": "实时语音 Playground",
+ "emptyHint": "点击「连接」开始实时会话。您可以使用麦克风说话或输入文字,AI 将以语音和文字回复。",
+ "you": "您",
+ "ai": "AI",
+ "stopRecording": "停止录音",
+ "startRecording": "开始录音",
+ "inputPlaceholder": "输入消息或使用麦克风...",
+ "listeningHint": "正在监听 — 请对麦克风说话,服务器 VAD 将检测您何时停止说话。"
+ },
+ "responseMetrics": {
+ "timeToFirstToken": "首 Token 时间",
+ "totalLatency": "总延迟",
+ "promptTokens": "提示词 Token",
+ "completionTokens": "补全 Token",
+ "reasoningTokens": "推理 Token",
+ "totalTokens": "总 Token",
+ "cost": "费用",
+ "toolUsed": "使用的工具",
+ "ttft": "TTFT:{{value}}s",
+ "totalLatencyValue": "总延迟:{{value}}s",
+ "in": "输入:{{count}}",
+ "out": "输出:{{count}}",
+ "reasoning": "推理:{{count}}",
+ "total": "总计:{{count}}",
+ "toolName": "工具:{{name}}"
+ },
+ "searchResultsDisplay": {
+ "hideSources": "隐藏来源",
+ "showSources": "显示来源({{count}})",
+ "query": "查询:",
+ "resultCount_one": "{{count}} 条结果",
+ "resultCount_other": "{{count}} 条结果",
+ "metadata": "元数据:"
+ },
+ "sessionManagement": {
+ "title": "会话管理",
+ "toggleTooltip": "在 LiteLLM API 会话管理(使用 previous_response_id)和基于 UI 的会话管理(使用聊天历史)之间选择",
+ "copiedToClipboard": "响应 ID 已复制到剪贴板!",
+ "apiSessionReady": "API 会话:就绪",
+ "uiSessionReady": "UI 会话:就绪",
+ "responseIdPrefix": "响应 ID",
+ "uiSessionPrefix": "UI 会话",
+ "apiSessionReadyDesc": "LiteLLM 将使用 previous_response_id 管理会话",
+ "uiSessionReadyDesc": "UI 将使用聊天历史管理会话",
+ "apiSessionActiveDesc": "LiteLLM API 会话活跃 - 上下文在服务端维护",
+ "uiSessionActiveDesc": "UI 会话活跃 - 上下文在客户端维护",
+ "copyTooltipTitle": "复制响应 ID 以继续会话:"
}
},
"settingsPages": {
@@ -4365,6 +5014,7 @@
"categories": "分类",
"showingCount": "显示 {{filtered}} / {{total}} 个模板",
"noTemplatesMatch": "没有模板匹配所选筛选条件。",
+ "clearAll": "清除全部",
"clearAllFilters": "清除所有筛选",
"complexityLabel": "{{complexity}} 复杂度",
"inheritsFrom": "继承自:",
@@ -4773,6 +5423,7 @@
"colPerRequest": "每次请求",
"colMarginFee": "利润率费用",
"totalPerRequest": "每次请求总计",
+ "breakdownTotalPerRequest": "总计/请求",
"totalPeriod": "{{periodLabel}}总计",
"marginFeePerRequest": "利润率费用/请求",
"periodMarginFeeTotal": "{{periodLabel}}利润率费用",
@@ -5052,5 +5703,178 @@
"tableView": "表格",
"chartView": "图表"
}
+ },
+ "vectorStoreProviders": {
+ "pgVector": {
+ "apiBaseLabel": "API 基础 URL",
+ "apiBaseTooltip": "输入您部署的 litellm-pgvector 服务器的基础 URL(例如:http://your-server:8000)",
+ "apiKeyLabel": "API 密钥",
+ "apiKeyTooltip": "输入您部署的 litellm-pgvector 服务器的 API 密钥"
+ },
+ "vertexAiSearch": {
+ "vertexProjectLabel": "Vertex 项目",
+ "vertexProjectTooltip": "托管 Vertex AI Search 数据存储的 Google Cloud 项目 ID。",
+ "vertexLocationLabel": "Vertex 位置",
+ "vertexLocationTooltip": "Vertex AI Search 数据存储位置,必须为 global、us 或 eu 之一。",
+ "vertexCollectionIdLabel": "集合 ID(可选)",
+ "vertexCollectionIdTooltip": "Discovery Engine 集合 ID。留空则使用默认集合。",
+ "vertexEngineIdLabel": "引擎 ID(可选)",
+ "vertexEngineIdTooltip": "搜索应用(引擎)ID。对于网站、医疗和基于连接器的数据存储(Workspace、Slack、Jira 等)为必填,因为这些来源通过引擎路由搜索。留空则直接查询数据存储。"
+ },
+ "openai": {
+ "apiKeyLabel": "API 密钥",
+ "apiKeyTooltip": "输入您的 OpenAI API 密钥"
+ },
+ "azure": {
+ "apiKeyLabel": "API 密钥",
+ "apiKeyTooltip": "输入您的 Azure OpenAI API 密钥",
+ "apiBaseLabel": "API 基础 URL",
+ "apiBaseTooltip": "输入您的 Azure OpenAI 端点(例如:https://your-resource.openai.azure.com/)"
+ },
+ "milvus": {
+ "apiKeyLabel": "API 密钥",
+ "apiKeyTooltip": "获取 Token 时,请使用冒号(:)连接您访问 Milvus 实例的用户名和密码(例如:username:password)",
+ "apiBaseLabel": "API 基础 URL",
+ "apiBaseTooltip": "输入您的 Milvus 端点(例如:https://your-milvus-endpoint.com/)",
+ "embeddingModelLabel": "嵌入模型",
+ "embeddingModelTooltip": "选择要使用的嵌入模型"
+ },
+ "s3Vectors": {
+ "vectorBucketNameLabel": "向量存储桶名称",
+ "vectorBucketNameTooltip": "用于向量存储的 S3 存储桶名称(若不存在则自动创建)",
+ "indexNameLabel": "索引名称",
+ "indexNameTooltip": "向量索引的名称(可选,若未提供则自动生成)",
+ "awsRegionLabel": "AWS 区域",
+ "awsRegionTooltip": "S3 存储桶所在的 AWS 区域(例如:us-west-2)",
+ "embeddingModelLabel": "嵌入模型",
+ "embeddingModelTooltip": "选择用于向量生成的嵌入模型"
+ }
+ },
+ "vectorStoreManagement": {
+ "createVectorStore": {
+ "pageTitle": "创建向量存储",
+ "pageSubtitle": "上传文档并选择提供商,以创建包含嵌入内容的新向量存储。",
+ "step1Title": "第 1 步:上传文档",
+ "step1Subtitle": "上传一个或多个文档(PDF、TXT、DOCX、MD)。每个文件最大 50MB。",
+ "draggerText": "点击或将文件拖拽到此区域以上传",
+ "draggerHint": "支持单个或批量上传。支持格式:PDF、TXT、DOCX、MD",
+ "uploadedDocuments": "已上传文档({{count}})",
+ "step2Title": "第 2 步:配置向量存储",
+ "step2Subtitle": "选择提供商,并可选填向量存储的名称和描述。",
+ "vectorStoreNameLabel": "向量存储名称",
+ "vectorStoreNameTooltip": "可选:为您的向量存储起一个有意义的名称",
+ "vectorStoreNamePlaceholder": "例如:产品文档、客户支持知识库",
+ "descriptionTooltip": "可选:描述此向量存储包含的内容",
+ "descriptionPlaceholder": "例如:包含所有产品文档和用户指南",
+ "providerLabel": "提供商",
+ "providerTooltip": "选择用于嵌入和向量存储操作的提供商",
+ "unsupportedFileType": "{{name}} 不是受支持的文件类型。请上传 PDF、TXT、DOCX 或 MD 文件。",
+ "fileTooLarge": "{{name}} 必须小于 50MB!",
+ "uploadAtLeastOne": "请至少上传一个文档",
+ "selectProvider": "请选择一个提供商",
+ "provideField": "请填写 {{label}}",
+ "bucketNameMinLength": "向量存储桶名称至少需要 3 个字符",
+ "indexNameMinLength": "若提供索引名称,至少需要 3 个字符",
+ "createSuccess": "成功创建向量存储,已包含 {{count}} 个文档。向量存储 ID:{{vectorStoreId}}",
+ "createFailed": "创建向量存储失败:{{error}}",
+ "creating": "正在创建向量存储...",
+ "createButton": "创建向量存储",
+ "successMessage": "向量存储创建成功",
+ "vectorStoreIdLabel": "向量存储 ID:",
+ "documentsIngestedLabel": "已摄入文档:"
+ },
+ "documentsTable": {
+ "idCopied": "文档 ID 已复制到剪贴板",
+ "statusUploading": "上传中",
+ "statusReady": "就绪",
+ "statusRemoved": "已移除",
+ "viewDetails": "查看详情",
+ "copyId": "复制 ID",
+ "emptyText": "尚未上传文档。请在上方上传文档以开始使用。"
+ },
+ "s3VectorsConfig": {
+ "alertTitle": "AWS S3 向量存储配置",
+ "alertDescription": "AWS S3 Vectors 允许您直接在 S3 中存储和查询向量嵌入:",
+ "alertItem1": "若向量存储桶和索引不存在,将自动创建",
+ "alertItem2": "向量维度会根据所选嵌入模型自动检测",
+ "alertItem3": "确保您的 AWS 凭据具有 S3 Vectors 操作权限",
+ "alertItem4Prefix": "了解更多:",
+ "alertItem4Link": "AWS S3 Vectors 文档",
+ "vectorBucketNameLabel": "向量存储桶名称",
+ "vectorBucketNameTooltip": "用于向量存储的 S3 存储桶名称(至少 3 个字符,仅限小写字母、数字、连字符和句点)",
+ "vectorBucketNamePlaceholder": "my-vector-bucket(最少 3 个字符)",
+ "bucketNameHelp": "存储桶名称至少需要 3 个字符",
+ "indexNameLabel": "索引名称",
+ "indexNameTooltip": "向量索引的名称(可选,若未提供则自动生成)。若提供,至少需要 3 个字符。",
+ "indexNamePlaceholder": "my-vector-index(可选,最少 3 个字符)",
+ "indexNameHelp": "若提供索引名称,至少需要 3 个字符",
+ "awsRegionLabel": "AWS 区域",
+ "awsRegionTooltip": "S3 存储桶所在的 AWS 区域(例如:us-west-2)",
+ "embeddingModelLabel": "嵌入模型",
+ "embeddingModelTooltip": "选择用于向量生成的嵌入模型",
+ "embeddingModelPlaceholder": "选择嵌入模型"
+ },
+ "testVectorStoreTab": {
+ "accessTokenRequired": "测试向量存储需要访问令牌。",
+ "noVectorStores": "暂无可用向量存储。请先创建一个再进行测试。",
+ "selectTitle": "选择向量存储",
+ "selectSubtitle": "选择一个向量存储以测试搜索查询",
+ "selectPlaceholder": "选择向量存储"
+ },
+ "vectorStoreForm": {
+ "modalTitle": "添加新向量存储",
+ "providerLabel": "提供商",
+ "providerTooltip": "为此向量存储选择提供商",
+ "providerRequired": "请选择一个提供商",
+ "pgVectorAlertTitle": "PG Vector 配置必需",
+ "pgVectorAlertDescription": "LiteLLM 提供了一个连接 PG Vector 的服务器。使用此提供商前:",
+ "pgVectorStep1": "从以下地址部署 litellm-pgvector 服务器:",
+ "pgVectorStep2": "为您的 PostgreSQL 数据库配置 pgvector 扩展",
+ "pgVectorStep3": "启动服务器并记录 API 基础 URL 和 API 密钥",
+ "pgVectorStep4": "在下方字段中输入这些详细信息",
+ "vertexRagAlertTitle": "Vertex AI RAG 引擎配置",
+ "vertexRagAlertDescription": "使用 Vertex AI RAG 引擎:",
+ "vertexRagStep1": "按照指南配置您的 Vertex AI RAG 引擎语料库:",
+ "vertexRagStep1Link": "Vertex AI RAG 引擎概述",
+ "vertexRagStep2": "在您的 Google Cloud 项目中创建语料库",
+ "vertexRagStep3": "从 Vertex AI 控制台记录语料库 ID",
+ "vertexRagStep4": "在下方的向量存储 ID 字段中输入语料库 ID",
+ "vertexSearchAlertTitle": "Vertex AI Search 配置",
+ "vertexSearchAlertDescription": "使用 Vertex AI Search(Discovery Engine):",
+ "vertexSearchStep1": "在您的 Google Cloud 项目上启用 Discovery Engine API 并按照指南创建数据存储:",
+ "vertexSearchStep1Link": "创建 Vertex AI Search 数据存储",
+ "vertexSearchStep2": "选择支持的位置:global、us 或 eu",
+ "vertexSearchStep3": "对于大多数数据存储类型(Cloud Storage、BigQuery、媒体):复制数据存储 ID 并在下方的向量存储 ID 字段中输入。",
+ "vertexSearchStep4": "对于网站、医疗和基于连接器的来源(Drive、Gmail、Slack、Jira 等):在数据存储之上创建搜索应用,然后复制引擎 ID 并在引擎 ID 字段中输入。此时向量存储 ID 仍为必填(作为 LiteLLM 侧的记录名称),但设置引擎 ID 后不会用于 GCP URL。",
+ "vectorStoreIdLabel": "向量存储 ID",
+ "vectorStoreIdTooltip": "输入您 API 提供商的向量存储 ID",
+ "vectorStoreIdRequired": "请输入您 API 提供商的向量存储 ID",
+ "vectorStoreIdPlaceholderVertexRag": "6917529027641081856(从 Vertex AI 控制台获取语料库 ID)",
+ "vectorStoreIdPlaceholderVertexSearch": "my-datastore_1234567890(从 Vertex AI Search 控制台获取数据存储 ID)",
+ "vectorStoreIdPlaceholderVertexSearchEngine": "您在 LiteLLM 中引用此记录的任意标识符",
+ "vectorStoreIdPlaceholderDefault": "输入提供商的向量存储 ID",
+ "fieldSelectRequired": "请选择 {{label}}",
+ "fieldInputRequired": "请输入 {{label}}",
+ "vectorStoreNameLabel": "向量存储名称",
+ "vectorStoreNameTooltip": "您要为向量存储起的自定义名称,此名称将在 LiteLLM 界面上显示",
+ "existingCredentialsLabel": "现有凭据",
+ "existingCredentialsTooltip": "可选:为此向量存储选择 API 提供商凭据,例如 Bedrock API 密钥",
+ "existingCredentialsPlaceholder": "选择或搜索现有凭据",
+ "metadataLabel": "元数据",
+ "metadataTooltip": "向量存储的 JSON 元数据(可选)",
+ "invalidMetadataJson": "元数据字段中的 JSON 无效",
+ "createSuccess": "向量存储创建成功",
+ "createFailed": "创建向量存储失败:{{error}}"
+ },
+ "vectorStoreTable": {
+ "colVectorStoreId": "向量存储 ID",
+ "colFiles": "文件",
+ "colProvider": "提供商",
+ "oneFile": "1 个文件",
+ "nFiles": "{{count}} 个文件",
+ "editTooltip": "编辑向量存储",
+ "deleteTooltip": "删除向量存储",
+ "noVectorStores": "未找到向量存储"
+ }
}
}