From c8228990a80b69a6fb3fa54748db762cf9763d69 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 05:44:34 +0900 Subject: [PATCH] feat(ui): i18n for cache settings --- .../cache_settings/CacheFieldRenderer.tsx | 4 +- .../cache_settings/RedisTypeSelector.tsx | 14 ++++--- .../src/components/cache_settings/index.tsx | 42 +++++++++++-------- ui/litellm-dashboard/src/locales/en.json | 33 +++++++++++++++ ui/litellm-dashboard/src/locales/zh-CN.json | 33 +++++++++++++++ 5 files changed, 101 insertions(+), 25 deletions(-) diff --git a/ui/litellm-dashboard/src/components/cache_settings/CacheFieldRenderer.tsx b/ui/litellm-dashboard/src/components/cache_settings/CacheFieldRenderer.tsx index eeabda23f9f..13bbf549e08 100644 --- a/ui/litellm-dashboard/src/components/cache_settings/CacheFieldRenderer.tsx +++ b/ui/litellm-dashboard/src/components/cache_settings/CacheFieldRenderer.tsx @@ -4,6 +4,7 @@ import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; import { NumberInput, TextInput } from "@tremor/react"; import { Select } from "antd"; import React, { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; import { fetchAvailableModels, ModelGroup } from "../playground/llm_calls/fetch_models"; import NumericalInput from "../shared/numerical_input"; @@ -16,6 +17,7 @@ const CacheFieldRenderer: React.FC = ({ field, currentV const [modelInfo, setModelInfo] = useState([]); const [selectedModel, setSelectedModel] = useState(currentValue || ""); const { accessToken } = useAuthorized(); + const { t } = useTranslation(); useEffect(() => { if (!accessToken) return; @@ -99,7 +101,7 @@ const CacheFieldRenderer: React.FC = ({ field, currentV value={selectedModel} onChange={setSelectedModel} showSearch={true} - placeholder="Search and select a model..." + placeholder={t("cacheSettings.cacheFieldRenderer.searchAndSelectModel")} options={embeddingModels} style={{ width: "100%" }} className="rounded-md" diff --git a/ui/litellm-dashboard/src/components/cache_settings/RedisTypeSelector.tsx b/ui/litellm-dashboard/src/components/cache_settings/RedisTypeSelector.tsx index a94d44dd4e0..1f448564c00 100644 --- a/ui/litellm-dashboard/src/components/cache_settings/RedisTypeSelector.tsx +++ b/ui/litellm-dashboard/src/components/cache_settings/RedisTypeSelector.tsx @@ -1,5 +1,6 @@ import React from "react"; import { Select, SelectItem } from "@tremor/react"; +import { useTranslation } from "react-i18next"; interface RedisTypeSelectorProps { redisType: string; @@ -8,17 +9,18 @@ interface RedisTypeSelectorProps { } const RedisTypeSelector: React.FC = ({ redisType, redisTypeDescriptions, onTypeChange }) => { + const { t } = useTranslation(); return (
- +

- {redisTypeDescriptions[redisType] || "Select the type of Redis deployment you're using"} + {redisTypeDescriptions[redisType] || t("cacheSettings.redisTypeSelector.selectTypeDescription")}

); diff --git a/ui/litellm-dashboard/src/components/cache_settings/index.tsx b/ui/litellm-dashboard/src/components/cache_settings/index.tsx index c7d8c579af3..6dd5f4576f6 100644 --- a/ui/litellm-dashboard/src/components/cache_settings/index.tsx +++ b/ui/litellm-dashboard/src/components/cache_settings/index.tsx @@ -1,4 +1,5 @@ import React, { useState, useEffect, useCallback } from "react"; +import { useTranslation } from "react-i18next"; import { Button, Accordion, AccordionHeader, AccordionBody } from "@tremor/react"; import { getCacheSettingsCall, testCacheConnectionCall, updateCacheSettingsCall } from "../networking"; import NotificationsManager from "../molecules/notifications_manager"; @@ -13,6 +14,7 @@ interface CacheSettingsProps { } const CacheSettings: React.FC = ({ accessToken, userRole, userID }) => { + const { t } = useTranslation(); const [cacheSettings, setCacheSettings] = useState<{ [key: string]: any }>({}); const [fields, setFields] = useState([]); const [redisTypeDescriptions, setRedisTypeDescriptions] = useState<{ [key: string]: string }>({}); @@ -43,7 +45,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us } } catch (error) { console.error("Failed to load cache settings:", error); - NotificationsManager.fromBackend("Failed to load cache settings"); + NotificationsManager.fromBackend(t("cacheSettings.index.failedToLoad")); } }, [accessToken]); @@ -65,13 +67,17 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us const result = await testCacheConnectionCall(accessToken, testSettings); if (result.status === "success") { - NotificationsManager.success("Cache connection test successful!"); + NotificationsManager.success(t("cacheSettings.index.testSuccessful")); } else { - NotificationsManager.fromBackend(`Connection test failed: ${result.message || result.error}`); + NotificationsManager.fromBackend( + t("cacheSettings.index.testFailed", { message: result.message || result.error }), + ); } } catch (error: any) { console.error("Test connection error:", error); - NotificationsManager.fromBackend(`Connection test failed: ${error.message || "Unknown error"}`); + NotificationsManager.fromBackend( + t("cacheSettings.index.testFailed", { message: error.message || t("common.unknown") }), + ); } finally { setIsTesting(false); } @@ -89,12 +95,12 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us settingsToSave.type = "redis-semantic"; } await updateCacheSettingsCall(accessToken, settingsToSave); - NotificationsManager.success("Cache settings updated successfully"); + NotificationsManager.success(t("cacheSettings.index.updateSuccess")); // Reload settings to reflect saved values await loadCacheSettings(); } catch (error) { console.error("Failed to save cache settings:", error); - NotificationsManager.fromBackend("Failed to update cache settings"); + NotificationsManager.fromBackend(t("cacheSettings.index.failedToUpdate")); } finally { setIsSaving(false); } @@ -111,8 +117,8 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us
-

Cache Settings

-

Configure Redis cache for LiteLLM

+

{t("cacheSettings.index.title")}

+

{t("cacheSettings.index.subtitle")}

{/* Redis Type Selector */} @@ -124,7 +130,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* Basic Fields */}
-

Connection Settings

+

{t("cacheSettings.index.connectionSettings")}

{basicFields.map((field: any) => { if (!field) return null; @@ -137,7 +143,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* Redis Type-Specific Fields */} {redisType === "cluster" && clusterFields.length > 0 && (
-

Cluster Configuration

+

{t("cacheSettings.index.clusterConfiguration")}

{clusterFields.map((field: any) => { const currentValue = cacheSettings[field.field_name] ?? field.field_default ?? ""; @@ -149,7 +155,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {redisType === "sentinel" && sentinelFields.length > 0 && (
-

Sentinel Configuration

+

{t("cacheSettings.index.sentinelConfiguration")}

{sentinelFields.map((field: any) => { const currentValue = cacheSettings[field.field_name] ?? field.field_default ?? ""; @@ -161,7 +167,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {redisType === "semantic" && semanticFields.length > 0 && (
-

Semantic Configuration

+

{t("cacheSettings.index.semanticConfiguration")}

{semanticFields.map((field: any) => { const currentValue = cacheSettings[field.field_name] ?? field.field_default ?? ""; @@ -174,14 +180,14 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* Advanced Settings Accordion */} - Advanced Settings + {t("cacheSettings.index.advancedSettings")}
{/* SSL Settings */} {sslFields.length > 0 && (
-
SSL Settings
+
{t("cacheSettings.index.sslSettings")}
{sslFields.map((field: any) => { if (!field) return null; @@ -195,7 +201,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* Cache Management */} {cacheManagementFields.length > 0 && (
-
Cache Management
+
{t("cacheSettings.index.cacheManagement")}
{cacheManagementFields.map((field: any) => { if (!field) return null; @@ -209,7 +215,7 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* GCP Authentication */} {gcpFields.length > 0 && (
-
GCP Authentication
+
{t("cacheSettings.index.gcpAuthentication")}
{gcpFields.map((field: any) => { if (!field) return null; @@ -227,10 +233,10 @@ const CacheSettings: React.FC = ({ accessToken, userRole, us {/* Actions */}
diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index 5352da828b0..dce9b7a21d4 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -7675,5 +7675,38 @@ "weekly": "weekly", "monthly": "monthly" } + }, + "cacheSettings": { + "cacheFieldRenderer": { + "searchAndSelectModel": "Search and select a model..." + }, + "redisTypeSelector": { + "redisType": "Redis Type", + "nodeType": "Node (Single Instance)", + "clusterType": "Cluster", + "sentinelType": "Sentinel", + "semanticType": "Semantic", + "selectTypeDescription": "Select the type of Redis deployment you're using" + }, + "index": { + "failedToLoad": "Failed to load cache settings", + "testSuccessful": "Cache connection test successful!", + "testFailed": "Connection test failed: {{message}}", + "updateSuccess": "Cache settings updated successfully", + "failedToUpdate": "Failed to update cache settings", + "title": "Cache Settings", + "subtitle": "Configure Redis cache for LiteLLM", + "connectionSettings": "Connection Settings", + "clusterConfiguration": "Cluster Configuration", + "sentinelConfiguration": "Sentinel Configuration", + "semanticConfiguration": "Semantic Configuration", + "advancedSettings": "Advanced Settings", + "sslSettings": "SSL Settings", + "cacheManagement": "Cache Management", + "gcpAuthentication": "GCP Authentication", + "testing": "Testing...", + "testConnection": "Test Connection", + "saveChanges": "Save Changes" + } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index 2d1324c08f6..0b670bed35f 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -7675,5 +7675,38 @@ "weekly": "每周", "monthly": "每月" } + }, + "cacheSettings": { + "cacheFieldRenderer": { + "searchAndSelectModel": "搜索并选择模型..." + }, + "redisTypeSelector": { + "redisType": "Redis 类型", + "nodeType": "节点(单实例)", + "clusterType": "集群", + "sentinelType": "哨兵", + "semanticType": "语义", + "selectTypeDescription": "选择您使用的 Redis 部署类型" + }, + "index": { + "failedToLoad": "加载缓存设置失败", + "testSuccessful": "缓存连接测试成功!", + "testFailed": "连接测试失败:{{message}}", + "updateSuccess": "缓存设置已成功更新", + "failedToUpdate": "更新缓存设置失败", + "title": "缓存设置", + "subtitle": "为 LiteLLM 配置 Redis 缓存", + "connectionSettings": "连接设置", + "clusterConfiguration": "集群配置", + "sentinelConfiguration": "哨兵配置", + "semanticConfiguration": "语义配置", + "advancedSettings": "高级设置", + "sslSettings": "SSL 设置", + "cacheManagement": "缓存管理", + "gcpAuthentication": "GCP 身份验证", + "testing": "测试中...", + "testConnection": "测试连接", + "saveChanges": "保存更改" + } } }