diff --git a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCostTracking.tsx b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCostTracking.tsx index db3ea94bbf9..dde1e1cda7f 100644 --- a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCostTracking.tsx +++ b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCostTracking.tsx @@ -7,8 +7,10 @@ import CloudZeroCreationModal from "./CloudZeroCreateModal"; import { useQueryClient } from "@tanstack/react-query"; import { createQueryKeys } from "@/app/(dashboard)/hooks/common/queryKeysFactory"; import { CloudZeroIntegrationSettings } from "./CloudZeroIntegrationSettings"; +import { useTranslation } from "react-i18next"; export default function CloudZeroCostTracking() { + const { t } = useTranslation(); const { accessToken } = useAuthorized(); const { data: settings, isLoading, error } = useCloudZeroSettings(accessToken); const queryClient = useQueryClient(); @@ -28,7 +30,7 @@ export default function CloudZeroCostTracking() { if (isLoading) { return ( - Loading CloudZero settings... + {t("cloudZero.cloudZeroCostTracking.loadingSettings")} ); } @@ -37,7 +39,9 @@ export default function CloudZeroCostTracking() { return ( - Error loading CloudZero settings: {error instanceof Error ? error.message : String(error)} + {t("cloudZero.cloudZeroCostTracking.errorLoadingSettings", { + error: error instanceof Error ? error.message : String(error), + })} ); diff --git a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCreateModal.tsx b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCreateModal.tsx index 5f460cb7cb6..75b9fb58f16 100644 --- a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCreateModal.tsx +++ b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroCreateModal.tsx @@ -3,6 +3,7 @@ import MessageManager from "@/components/molecules/message_manager"; import { useEffect } from "react"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; import { useCloudZeroCreate } from "@/app/(dashboard)/hooks/cloudzero/useCloudZeroCreate"; +import { useTranslation } from "react-i18next"; interface CloudZeroCreationModalProps { open: boolean; @@ -11,6 +12,7 @@ interface CloudZeroCreationModalProps { } export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZeroCreationModalProps) { + const { t } = useTranslation(); const { accessToken } = useAuthorized(); const [form] = Form.useForm(); const createMutation = useCloudZeroCreate(accessToken || ""); @@ -32,7 +34,7 @@ export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZe }, { onSuccess: () => { - MessageManager.success("CloudZero integration created successfully"); + MessageManager.success(t("cloudZero.cloudZeroCreateModal.createSuccess")); form.resetFields(); onOk(); }, @@ -40,7 +42,7 @@ export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZe if (error?.errorFields) { return; } - MessageManager.error(error?.message || "Failed to create CloudZero integration"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroCreateModal.createFailed")); }, }, ); @@ -48,7 +50,7 @@ export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZe if (error?.errorFields) { return; } - MessageManager.error(error?.message || "Failed to create CloudZero integration"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroCreateModal.createFailed")); } }; @@ -59,13 +61,13 @@ export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZe return (
- + - + diff --git a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroEmptyPlaceholder.tsx b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroEmptyPlaceholder.tsx index aca074dc290..366b970c7a7 100644 --- a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroEmptyPlaceholder.tsx +++ b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroEmptyPlaceholder.tsx @@ -1,4 +1,5 @@ import { Empty, Typography, Button } from "antd"; +import { useTranslation } from "react-i18next"; const { Title, Paragraph } = Typography; @@ -7,21 +8,22 @@ interface CloudZeroEmptyPlaceholderProps { } export default function CloudZeroEmptyPlaceholder({ startCreation }: CloudZeroEmptyPlaceholderProps) { + const { t } = useTranslation(); return (
- No CloudZero Integration Found + {t("cloudZero.cloudZeroEmptyPlaceholder.title")} - Connect your CloudZero account to start tracking and analyzing your cloud costs directly from LiteLLM. + {t("cloudZero.cloudZeroEmptyPlaceholder.description")}
} > diff --git a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroIntegrationSettings.tsx b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroIntegrationSettings.tsx index 62709dac526..1714e3d384b 100644 --- a/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroIntegrationSettings.tsx +++ b/ui/litellm-dashboard/src/components/CloudZeroCostTracking/CloudZeroIntegrationSettings.tsx @@ -9,6 +9,7 @@ import { CheckCircle, Edit, Play, Trash2, Upload } from "lucide-react"; import { useState } from "react"; import CloudZeroUpdateModal from "./CloudZeroUpdateModal"; import { CloudZeroSettings } from "./types"; +import { useTranslation } from "react-i18next"; interface CloudZeroIntegrationSettingsProps { settings: CloudZeroSettings; @@ -16,6 +17,7 @@ interface CloudZeroIntegrationSettingsProps { } export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: CloudZeroIntegrationSettingsProps) { + const { t } = useTranslation(); const { accessToken } = useAuthorized(); const [isEditModalOpen, setIsEditModalOpen] = useState(false); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); @@ -31,10 +33,10 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl { limit: 10 }, { onSuccess: (data) => { - MessageManager.success("Dry run completed successfully"); + MessageManager.success(t("cloudZero.cloudZeroIntegrationSettings.dryRunSuccess")); }, onError: (error) => { - MessageManager.error(error?.message || "Failed to perform dry run"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroIntegrationSettings.dryRunFailed")); }, }, ); @@ -49,10 +51,10 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl { operation: "replace_hourly" }, { onSuccess: () => { - MessageManager.success("Data successfully exported to CloudZero"); + MessageManager.success(t("cloudZero.cloudZeroIntegrationSettings.exportSuccess")); }, onError: (error) => { - MessageManager.error(error?.message || "Failed to export data"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroIntegrationSettings.exportFailed")); }, }, ); @@ -80,12 +82,12 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl deleteMutation.mutate(undefined, { onSuccess: () => { - MessageManager.success("CloudZero integration deleted successfully"); + MessageManager.success(t("cloudZero.cloudZeroIntegrationSettings.deleteSuccess")); setIsDeleteModalOpen(false); onSettingsUpdated(); }, onError: (error) => { - MessageManager.error(error?.message || "Failed to delete CloudZero integration"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroIntegrationSettings.deleteFailed")); }, }); }; @@ -100,16 +102,16 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl - CloudZero Configuration + {t("cloudZero.cloudZeroIntegrationSettings.cardTitle")} - {settings.status || "Active"} + {settings.status || t("common.active")} } extra={
} @@ -134,23 +136,33 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl xs: 1, }} > - + - {settings.api_key_masked || Not configured} + {settings.api_key_masked || ( + + {t("cloudZero.cloudZeroIntegrationSettings.notConfigured")} + + )} - + - {settings.connection_id || Not configured} + {settings.connection_id || ( + + {t("cloudZero.cloudZeroIntegrationSettings.notConfigured")} + + )} - - {settings.timezone || Default (UTC)} + + {settings.timezone || ( + {t("cloudZero.cloudZeroIntegrationSettings.defaultUtc")} + )} - Actions + {t("common.actions")}
@@ -160,15 +172,15 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl icon={} className="flex items-center gap-2" > - Run Dry Run Simulation + {t("cloudZero.cloudZeroIntegrationSettings.runDryRun")}
@@ -184,10 +196,14 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl {dryRunResult && (
-

Simulation output for connection: {settings.connection_id}

+

+ {t("cloudZero.cloudZeroIntegrationSettings.dryRunSimulationOutput", { + connectionId: settings.connection_id, + })} +

                       {dryRunResult}
                     
@@ -211,18 +227,18 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl { - MessageManager.success("CloudZero integration updated successfully"); + MessageManager.success(t("cloudZero.cloudZeroUpdateModal.updateSuccess")); form.resetFields(); onOk(); }, @@ -48,7 +50,7 @@ export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }: if (error?.errorFields) { return; } - MessageManager.error(error?.message || "Failed to update CloudZero integration"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroUpdateModal.updateFailed")); }, }, ); @@ -56,7 +58,7 @@ export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }: if (error?.errorFields) { return; } - MessageManager.error(error?.message || "Failed to update CloudZero integration"); + MessageManager.error(error?.message || t("cloudZero.cloudZeroUpdateModal.updateFailed")); } }; @@ -67,13 +69,13 @@ export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }: return ( - + - + diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index 21f4b4d34c6..e1cd79fb39f 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -7059,5 +7059,69 @@ "deleteMessage": "Are you sure you want to delete this access group? This action cannot be undone.", "resourceInfoTitle": "Access Group Information" } + }, + "cloudZero": { + "cloudZeroCostTracking": { + "loadingSettings": "Loading CloudZero settings...", + "errorLoadingSettings": "Error loading CloudZero settings: {{error}}" + }, + "cloudZeroCreateModal": { + "title": "Create CloudZero Integration", + "creating": "Creating...", + "createSuccess": "CloudZero integration created successfully", + "createFailed": "Failed to create CloudZero integration", + "apiKeyLabel": "CloudZero API Key", + "apiKeyRequired": "Please enter your CloudZero API key", + "apiKeyPlaceholder": "Enter your CloudZero API key", + "connectionIdLabel": "Connection ID", + "connectionIdRequired": "Please enter your CloudZero connection ID", + "connectionIdPlaceholder": "Enter your CloudZero connection ID", + "timezoneLabel": "Timezone", + "timezoneTooltip": "Timezone for date handling (defaults to UTC if not provided)" + }, + "cloudZeroEmptyPlaceholder": { + "title": "No CloudZero Integration Found", + "description": "Connect your CloudZero account to start tracking and analyzing your cloud costs directly from LiteLLM.", + "addButton": "Add CloudZero Integration" + }, + "cloudZeroIntegrationSettings": { + "cardTitle": "CloudZero Configuration", + "apiKeyRedacted": "API Key (Redacted)", + "connectionId": "Connection ID", + "timezone": "Timezone", + "notConfigured": "Not configured", + "defaultUtc": "Default (UTC)", + "runDryRun": "Run Dry Run Simulation", + "exportPopconfirmTitle": "Export Data to CloudZero", + "exportPopconfirmDescription": "This will push the current accumulated cost data to CloudZero. Continue?", + "exportOkText": "Export", + "exportDataNow": "Export Data Now", + "dryRunSuccess": "Dry run completed successfully", + "dryRunFailed": "Failed to perform dry run", + "exportSuccess": "Data successfully exported to CloudZero", + "exportFailed": "Failed to export data", + "deleteSuccess": "CloudZero integration deleted successfully", + "deleteFailed": "Failed to delete CloudZero integration", + "dryRunResultsTitle": "Dry Run Results", + "dryRunSimulationOutput": "Simulation output for connection: {{connectionId}}", + "deleteModalTitle": "Delete CloudZero Integration?", + "deleteModalMessage": "Are you sure you want to delete this CloudZero integration? All associated settings and configurations will be permanently removed.", + "integrationDetails": "Integration Details" + }, + "cloudZeroUpdateModal": { + "title": "Edit CloudZero Integration", + "updating": "Updating...", + "updateSuccess": "CloudZero integration updated successfully", + "updateFailed": "Failed to update CloudZero integration", + "apiKeyLabel": "CloudZero API Key", + "apiKeyRuleMessage": "Please enter your CloudZero API key", + "apiKeyTooltip": "Leave empty to keep the existing API key", + "apiKeyPlaceholder": "Leave empty to keep existing", + "connectionIdLabel": "Connection ID", + "connectionIdRequired": "Please enter your CloudZero connection ID", + "connectionIdPlaceholder": "Enter your CloudZero connection ID", + "timezoneLabel": "Timezone", + "timezoneTooltip": "Timezone for date handling (defaults to UTC if not provided)" + } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index 1c90fd4a736..431f27d0a4a 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -7059,5 +7059,69 @@ "deleteMessage": "确定要删除此访问组吗?此操作无法撤销。", "resourceInfoTitle": "访问组信息" } + }, + "cloudZero": { + "cloudZeroCostTracking": { + "loadingSettings": "正在加载 CloudZero 设置...", + "errorLoadingSettings": "加载 CloudZero 设置时出错:{{error}}" + }, + "cloudZeroCreateModal": { + "title": "创建 CloudZero 集成", + "creating": "创建中...", + "createSuccess": "CloudZero 集成已成功创建", + "createFailed": "创建 CloudZero 集成失败", + "apiKeyLabel": "CloudZero API 密钥", + "apiKeyRequired": "请输入您的 CloudZero API 密钥", + "apiKeyPlaceholder": "输入您的 CloudZero API 密钥", + "connectionIdLabel": "Connection ID", + "connectionIdRequired": "请输入您的 CloudZero 连接 ID", + "connectionIdPlaceholder": "输入您的 CloudZero 连接 ID", + "timezoneLabel": "时区", + "timezoneTooltip": "日期处理时区(未提供时默认为 UTC)" + }, + "cloudZeroEmptyPlaceholder": { + "title": "未找到 CloudZero 集成", + "description": "连接您的 CloudZero 账户,即可直接在 LiteLLM 中追踪和分析云端成本。", + "addButton": "添加 CloudZero 集成" + }, + "cloudZeroIntegrationSettings": { + "cardTitle": "CloudZero 配置", + "apiKeyRedacted": "API 密钥(已脱敏)", + "connectionId": "Connection ID", + "timezone": "时区", + "notConfigured": "未配置", + "defaultUtc": "默认 (UTC)", + "runDryRun": "运行试运行模拟", + "exportPopconfirmTitle": "将数据导出至 CloudZero", + "exportPopconfirmDescription": "此操作将把当前累计的成本数据推送至 CloudZero。是否继续?", + "exportOkText": "导出", + "exportDataNow": "立即导出数据", + "dryRunSuccess": "试运行已成功完成", + "dryRunFailed": "执行试运行失败", + "exportSuccess": "数据已成功导出至 CloudZero", + "exportFailed": "导出数据失败", + "deleteSuccess": "CloudZero 集成已成功删除", + "deleteFailed": "删除 CloudZero 集成失败", + "dryRunResultsTitle": "试运行结果", + "dryRunSimulationOutput": "连接 {{connectionId}} 的模拟输出", + "deleteModalTitle": "删除 CloudZero 集成?", + "deleteModalMessage": "确定要删除此 CloudZero 集成吗?所有相关设置和配置将被永久移除。", + "integrationDetails": "集成详情" + }, + "cloudZeroUpdateModal": { + "title": "编辑 CloudZero 集成", + "updating": "更新中...", + "updateSuccess": "CloudZero 集成已成功更新", + "updateFailed": "更新 CloudZero 集成失败", + "apiKeyLabel": "CloudZero API 密钥", + "apiKeyRuleMessage": "请输入您的 CloudZero API 密钥", + "apiKeyTooltip": "留空则保留现有 API 密钥", + "apiKeyPlaceholder": "留空则保留现有密钥", + "connectionIdLabel": "Connection ID", + "connectionIdRequired": "请输入您的 CloudZero 连接 ID", + "connectionIdPlaceholder": "输入您的 CloudZero 连接 ID", + "timezoneLabel": "时区", + "timezoneTooltip": "日期处理时区(未提供时默认为 UTC)" + } } }