mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for CloudZero cost tracking
This commit is contained in:
parent
cd547a117b
commit
663681bc4e
7 changed files with 219 additions and 65 deletions
|
|
@ -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 (
|
||||
<Card>
|
||||
<Typography.Text>Loading CloudZero settings...</Typography.Text>
|
||||
<Typography.Text>{t("cloudZero.cloudZeroCostTracking.loadingSettings")}</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -37,7 +39,9 @@ export default function CloudZeroCostTracking() {
|
|||
return (
|
||||
<Card>
|
||||
<Typography.Text className="text-red-600">
|
||||
Error loading CloudZero settings: {error instanceof Error ? error.message : String(error)}
|
||||
{t("cloudZero.cloudZeroCostTracking.errorLoadingSettings", {
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
})}
|
||||
</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<Modal
|
||||
title="Create CloudZero Integration"
|
||||
title={t("cloudZero.cloudZeroCreateModal.title")}
|
||||
open={open}
|
||||
onOk={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
confirmLoading={createMutation.isPending}
|
||||
okText={createMutation.isPending ? "Creating..." : "Create"}
|
||||
cancelText="Cancel"
|
||||
okText={createMutation.isPending ? t("cloudZero.cloudZeroCreateModal.creating") : t("common.create")}
|
||||
cancelText={t("common.cancel")}
|
||||
okButtonProps={{
|
||||
disabled: createMutation.isPending,
|
||||
}}
|
||||
|
|
@ -75,23 +77,23 @@ export default function CloudZeroCreationModal({ open, onOk, onCancel }: CloudZe
|
|||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item
|
||||
label="CloudZero API Key"
|
||||
label={t("cloudZero.cloudZeroCreateModal.apiKeyLabel")}
|
||||
name="api_key"
|
||||
rules={[{ required: true, message: "Please enter your CloudZero API key" }]}
|
||||
rules={[{ required: true, message: t("cloudZero.cloudZeroCreateModal.apiKeyRequired") }]}
|
||||
>
|
||||
<Input.Password placeholder="Enter your CloudZero API key" />
|
||||
<Input.Password placeholder={t("cloudZero.cloudZeroCreateModal.apiKeyPlaceholder")} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Connection ID"
|
||||
label={t("cloudZero.cloudZeroCreateModal.connectionIdLabel")}
|
||||
name="connection_id"
|
||||
rules={[{ required: true, message: "Please enter your CloudZero connection ID" }]}
|
||||
rules={[{ required: true, message: t("cloudZero.cloudZeroCreateModal.connectionIdRequired") }]}
|
||||
>
|
||||
<Input placeholder="Enter your CloudZero connection ID" />
|
||||
<Input placeholder={t("cloudZero.cloudZeroCreateModal.connectionIdPlaceholder")} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Timezone"
|
||||
label={t("cloudZero.cloudZeroCreateModal.timezoneLabel")}
|
||||
name="timezone"
|
||||
tooltip="Timezone for date handling (defaults to UTC if not provided)"
|
||||
tooltip={t("cloudZero.cloudZeroCreateModal.timezoneTooltip")}
|
||||
>
|
||||
<Input placeholder="UTC" />
|
||||
</Form.Item>
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className="bg-white p-12 rounded-lg border border-dashed border-gray-300 text-center max-w-2xl mx-auto mt-8">
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description={
|
||||
<div className="space-y-2">
|
||||
<Title level={4}>No CloudZero Integration Found</Title>
|
||||
<Title level={4}>{t("cloudZero.cloudZeroEmptyPlaceholder.title")}</Title>
|
||||
<Paragraph type="secondary" className="max-w-md mx-auto">
|
||||
Connect your CloudZero account to start tracking and analyzing your cloud costs directly from LiteLLM.
|
||||
{t("cloudZero.cloudZeroEmptyPlaceholder.description")}
|
||||
</Paragraph>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Button type="primary" size="large" onClick={startCreation} className="flex items-center gap-2 mx-auto mt-4">
|
||||
Add CloudZero Integration
|
||||
{t("cloudZero.cloudZeroEmptyPlaceholder.addButton")}
|
||||
</Button>
|
||||
</Empty>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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
|
|||
<Card
|
||||
title={
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-lg font-semibold">CloudZero Configuration</span>
|
||||
<span className="text-lg font-semibold">{t("cloudZero.cloudZeroIntegrationSettings.cardTitle")}</span>
|
||||
<Tag color="success" className="ml-2 capitalize">
|
||||
{settings.status || "Active"}
|
||||
{settings.status || t("common.active")}
|
||||
</Tag>
|
||||
</div>
|
||||
}
|
||||
extra={
|
||||
<div className="flex gap-2">
|
||||
<Button icon={<Edit size={16} />} onClick={handleEdit} className="flex items-center gap-2">
|
||||
Edit
|
||||
{t("common.edit")}
|
||||
</Button>
|
||||
<Button
|
||||
danger
|
||||
|
|
@ -117,7 +119,7 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
onClick={handleDeleteClick}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
Delete
|
||||
{t("common.delete")}
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
|
|
@ -134,23 +136,33 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
xs: 1,
|
||||
}}
|
||||
>
|
||||
<Descriptions.Item label="API Key (Redacted)">
|
||||
<Descriptions.Item label={t("cloudZero.cloudZeroIntegrationSettings.apiKeyRedacted")}>
|
||||
<span className="font-mono text-gray-600">
|
||||
{settings.api_key_masked || <span className="text-gray-400 italic">Not configured</span>}
|
||||
{settings.api_key_masked || (
|
||||
<span className="text-gray-400 italic">
|
||||
{t("cloudZero.cloudZeroIntegrationSettings.notConfigured")}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Connection ID">
|
||||
<Descriptions.Item label={t("cloudZero.cloudZeroIntegrationSettings.connectionId")}>
|
||||
<span className="font-mono text-gray-600">
|
||||
{settings.connection_id || <span className="text-gray-400 italic">Not configured</span>}
|
||||
{settings.connection_id || (
|
||||
<span className="text-gray-400 italic">
|
||||
{t("cloudZero.cloudZeroIntegrationSettings.notConfigured")}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="Timezone">
|
||||
{settings.timezone || <span className="text-gray-400 italic">Default (UTC)</span>}
|
||||
<Descriptions.Item label={t("cloudZero.cloudZeroIntegrationSettings.timezone")}>
|
||||
{settings.timezone || (
|
||||
<span className="text-gray-400 italic">{t("cloudZero.cloudZeroIntegrationSettings.defaultUtc")}</span>
|
||||
)}
|
||||
</Descriptions.Item>
|
||||
</Descriptions>
|
||||
|
||||
<Divider orientation="left" className="text-gray-500">
|
||||
Actions
|
||||
{t("common.actions")}
|
||||
</Divider>
|
||||
|
||||
<div className="flex flex-wrap gap-4 mb-6">
|
||||
|
|
@ -160,15 +172,15 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
icon={<Play size={16} />}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
Run Dry Run Simulation
|
||||
{t("cloudZero.cloudZeroIntegrationSettings.runDryRun")}
|
||||
</Button>
|
||||
|
||||
<Popconfirm
|
||||
title="Export Data to CloudZero"
|
||||
description="This will push the current accumulated cost data to CloudZero. Continue?"
|
||||
title={t("cloudZero.cloudZeroIntegrationSettings.exportPopconfirmTitle")}
|
||||
description={t("cloudZero.cloudZeroIntegrationSettings.exportPopconfirmDescription")}
|
||||
onConfirm={handleExport}
|
||||
okText="Export"
|
||||
cancelText="Cancel"
|
||||
okText={t("cloudZero.cloudZeroIntegrationSettings.exportOkText")}
|
||||
cancelText={t("common.cancel")}
|
||||
>
|
||||
<Button
|
||||
type="primary"
|
||||
|
|
@ -176,7 +188,7 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
icon={<Upload size={16} />}
|
||||
className="flex items-center gap-2"
|
||||
>
|
||||
Export Data Now
|
||||
{t("cloudZero.cloudZeroIntegrationSettings.exportDataNow")}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</div>
|
||||
|
|
@ -184,10 +196,14 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
{dryRunResult && (
|
||||
<div className="mt-6 animate-in fade-in slide-in-from-top-4 duration-300">
|
||||
<Alert
|
||||
message="Dry Run Results"
|
||||
message={t("cloudZero.cloudZeroIntegrationSettings.dryRunResultsTitle")}
|
||||
description={
|
||||
<div className="mt-2">
|
||||
<p className="mb-2 text-gray-600">Simulation output for connection: {settings.connection_id}</p>
|
||||
<p className="mb-2 text-gray-600">
|
||||
{t("cloudZero.cloudZeroIntegrationSettings.dryRunSimulationOutput", {
|
||||
connectionId: settings.connection_id,
|
||||
})}
|
||||
</p>
|
||||
<pre className="bg-gray-50 p-4 rounded-md border border-gray-200 overflow-x-auto text-xs font-mono text-gray-800">
|
||||
{dryRunResult}
|
||||
</pre>
|
||||
|
|
@ -211,18 +227,18 @@ export function CloudZeroIntegrationSettings({ settings, onSettingsUpdated }: Cl
|
|||
|
||||
<DeleteResourceModal
|
||||
isOpen={isDeleteModalOpen}
|
||||
title="Delete CloudZero Integration?"
|
||||
message="Are you sure you want to delete this CloudZero integration? All associated settings and configurations will be permanently removed."
|
||||
resourceInformationTitle="Integration Details"
|
||||
title={t("cloudZero.cloudZeroIntegrationSettings.deleteModalTitle")}
|
||||
message={t("cloudZero.cloudZeroIntegrationSettings.deleteModalMessage")}
|
||||
resourceInformationTitle={t("cloudZero.cloudZeroIntegrationSettings.integrationDetails")}
|
||||
resourceInformation={[
|
||||
{
|
||||
label: "Connection ID",
|
||||
label: t("cloudZero.cloudZeroIntegrationSettings.connectionId"),
|
||||
value: settings.connection_id,
|
||||
code: true,
|
||||
},
|
||||
{
|
||||
label: "Timezone",
|
||||
value: settings.timezone || "Default (UTC)",
|
||||
label: t("cloudZero.cloudZeroIntegrationSettings.timezone"),
|
||||
value: settings.timezone || t("cloudZero.cloudZeroIntegrationSettings.defaultUtc"),
|
||||
},
|
||||
]}
|
||||
onCancel={handleDeleteCancel}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { Form, Input, Modal } from "antd";
|
|||
import MessageManager from "@/components/molecules/message_manager";
|
||||
import { useEffect } from "react";
|
||||
import { CloudZeroSettings } from "./types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface CloudZeroUpdateModalProps {
|
||||
open: boolean;
|
||||
|
|
@ -13,6 +14,7 @@ interface CloudZeroUpdateModalProps {
|
|||
}
|
||||
|
||||
export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }: CloudZeroUpdateModalProps) {
|
||||
const { t } = useTranslation();
|
||||
const { accessToken } = useAuthorized();
|
||||
const [form] = Form.useForm();
|
||||
const updateMutation = useCloudZeroUpdateSettings(accessToken || "");
|
||||
|
|
@ -40,7 +42,7 @@ export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }:
|
|||
},
|
||||
{
|
||||
onSuccess: () => {
|
||||
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 (
|
||||
<Modal
|
||||
title="Edit CloudZero Integration"
|
||||
title={t("cloudZero.cloudZeroUpdateModal.title")}
|
||||
open={open}
|
||||
onOk={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
confirmLoading={updateMutation.isPending}
|
||||
okText={updateMutation.isPending ? "Updating..." : "Update"}
|
||||
cancelText="Cancel"
|
||||
okText={updateMutation.isPending ? t("cloudZero.cloudZeroUpdateModal.updating") : t("common.update")}
|
||||
cancelText={t("common.cancel")}
|
||||
okButtonProps={{
|
||||
disabled: updateMutation.isPending,
|
||||
}}
|
||||
|
|
@ -83,24 +85,24 @@ export default function CloudZeroUpdateModal({ open, onOk, onCancel, settings }:
|
|||
>
|
||||
<Form form={form} layout="vertical" onFinish={handleSubmit}>
|
||||
<Form.Item
|
||||
label="CloudZero API Key"
|
||||
label={t("cloudZero.cloudZeroUpdateModal.apiKeyLabel")}
|
||||
name="api_key"
|
||||
rules={[{ required: false, message: "Please enter your CloudZero API key" }]}
|
||||
tooltip="Leave empty to keep the existing API key"
|
||||
rules={[{ required: false, message: t("cloudZero.cloudZeroUpdateModal.apiKeyRuleMessage") }]}
|
||||
tooltip={t("cloudZero.cloudZeroUpdateModal.apiKeyTooltip")}
|
||||
>
|
||||
<Input.Password placeholder="Leave empty to keep existing" />
|
||||
<Input.Password placeholder={t("cloudZero.cloudZeroUpdateModal.apiKeyPlaceholder")} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Connection ID"
|
||||
label={t("cloudZero.cloudZeroUpdateModal.connectionIdLabel")}
|
||||
name="connection_id"
|
||||
rules={[{ required: true, message: "Please enter your CloudZero connection ID" }]}
|
||||
rules={[{ required: true, message: t("cloudZero.cloudZeroUpdateModal.connectionIdRequired") }]}
|
||||
>
|
||||
<Input placeholder="Enter your CloudZero connection ID" />
|
||||
<Input placeholder={t("cloudZero.cloudZeroUpdateModal.connectionIdPlaceholder")} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="Timezone"
|
||||
label={t("cloudZero.cloudZeroUpdateModal.timezoneLabel")}
|
||||
name="timezone"
|
||||
tooltip="Timezone for date handling (defaults to UTC if not provided)"
|
||||
tooltip={t("cloudZero.cloudZeroUpdateModal.timezoneTooltip")}
|
||||
>
|
||||
<Input placeholder="UTC" />
|
||||
</Form.Item>
|
||||
|
|
|
|||
|
|
@ -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)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue