mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for budgets
This commit is contained in:
parent
4b0371ae44
commit
c81c0265ec
5 changed files with 205 additions and 54 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import { TextInput, Accordion, AccordionHeader, AccordionBody } from "@tremor/react";
|
||||
import { Button as Button2, Modal, Form, InputNumber, Select } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCreateBudget } from "@/app/(dashboard)/hooks/budgets/useBudgets";
|
||||
import NotificationsManager from "../molecules/notifications_manager";
|
||||
|
||||
|
|
@ -9,6 +10,7 @@ interface BudgetModalProps {
|
|||
setIsModalVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
const BudgetModal: React.FC<BudgetModalProps> = ({ isModalVisible, setIsModalVisible }) => {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const createBudget = useCreateBudget();
|
||||
|
||||
|
|
@ -24,20 +26,20 @@ const BudgetModal: React.FC<BudgetModalProps> = ({ isModalVisible, setIsModalVis
|
|||
|
||||
const handleCreate = async (formValues: Record<string, any>) => {
|
||||
try {
|
||||
NotificationsManager.info("Making API Call");
|
||||
NotificationsManager.info(t("budgets.budgetModal.makingApiCall"));
|
||||
await createBudget.mutateAsync(formValues);
|
||||
NotificationsManager.success("Budget Created");
|
||||
NotificationsManager.success(t("budgets.budgetModal.budgetCreated"));
|
||||
form.resetFields();
|
||||
setIsModalVisible(false);
|
||||
} catch (error) {
|
||||
console.error("Error creating the budget:", error);
|
||||
NotificationsManager.fromBackend(`Error creating the budget: ${error}`);
|
||||
NotificationsManager.fromBackend(t("budgets.budgetModal.errorCreating", { error }));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Create Budget"
|
||||
title={t("budgets.budgetModal.title")}
|
||||
open={isModalVisible}
|
||||
width={800}
|
||||
footer={null}
|
||||
|
|
@ -47,38 +49,46 @@ const BudgetModal: React.FC<BudgetModalProps> = ({ isModalVisible, setIsModalVis
|
|||
<Form form={form} onFinish={handleCreate} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} labelAlign="left">
|
||||
<>
|
||||
<Form.Item
|
||||
label="Budget ID"
|
||||
label={t("budgets.budgetModal.budgetIdLabel")}
|
||||
name="budget_id"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input a human-friendly name for the budget",
|
||||
message: t("budgets.budgetModal.budgetIdRequired"),
|
||||
},
|
||||
]}
|
||||
help="A human-friendly name for the budget"
|
||||
help={t("budgets.budgetModal.budgetIdHelp")}
|
||||
>
|
||||
<TextInput placeholder="" />
|
||||
</Form.Item>
|
||||
<Form.Item label="Max Tokens per minute" name="tpm_limit" help="Default is model limit.">
|
||||
<Form.Item
|
||||
label={t("budgets.budgetModal.tpmLimitLabel")}
|
||||
name="tpm_limit"
|
||||
help={t("budgets.budgetModal.defaultModelLimit")}
|
||||
>
|
||||
<InputNumber step={1} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Max Requests per minute" name="rpm_limit" help="Default is model limit.">
|
||||
<Form.Item
|
||||
label={t("budgets.budgetModal.rpmLimitLabel")}
|
||||
name="rpm_limit"
|
||||
help={t("budgets.budgetModal.defaultModelLimit")}
|
||||
>
|
||||
<InputNumber step={1} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
|
||||
<Accordion className="mt-20 mb-8">
|
||||
<AccordionHeader>
|
||||
<b>Optional Settings</b>
|
||||
<b>{t("budgets.budgetModal.optionalSettings")}</b>
|
||||
</AccordionHeader>
|
||||
<AccordionBody>
|
||||
<Form.Item label="Max Budget (USD)" name="max_budget">
|
||||
<Form.Item label={t("budgets.budgetModal.maxBudgetLabel")} name="max_budget">
|
||||
<InputNumber step={0.01} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
<Form.Item className="mt-8" label="Reset Budget" name="budget_duration">
|
||||
<Form.Item className="mt-8" label={t("budgets.budgetModal.resetBudgetLabel")} name="budget_duration">
|
||||
<Select defaultValue={null} placeholder="n/a">
|
||||
<Select.Option value="24h">daily</Select.Option>
|
||||
<Select.Option value="7d">weekly</Select.Option>
|
||||
<Select.Option value="30d">monthly</Select.Option>
|
||||
<Select.Option value="24h">{t("budgets.budgetModal.daily")}</Select.Option>
|
||||
<Select.Option value="7d">{t("budgets.budgetModal.weekly")}</Select.Option>
|
||||
<Select.Option value="30d">{t("budgets.budgetModal.monthly")}</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</AccordionBody>
|
||||
|
|
@ -86,7 +96,7 @@ const BudgetModal: React.FC<BudgetModalProps> = ({ isModalVisible, setIsModalVis
|
|||
</>
|
||||
|
||||
<div style={{ textAlign: "right", marginTop: "10px" }}>
|
||||
<Button2 htmlType="submit">Create Budget</Button2>
|
||||
<Button2 htmlType="submit">{t("budgets.budgetModal.createBudgetButton")}</Button2>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import {
|
|||
Text,
|
||||
} from "@tremor/react";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||
import DeleteResourceModal from "../common_components/DeleteResourceModal";
|
||||
import TableIconActionButton from "../common_components/IconActionButton/TableIconActionButtons/TableIconActionButton";
|
||||
|
|
@ -44,6 +45,7 @@ export interface budgetItem {
|
|||
}
|
||||
|
||||
const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
||||
const { t } = useTranslation();
|
||||
const [isCreateModelVisible, setIsCreateModelVisible] = useState(false);
|
||||
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||
const [selectedBudget, setSelectedBudget] = useState<budgetItem | null>(null);
|
||||
|
|
@ -75,13 +77,13 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
}
|
||||
try {
|
||||
await deleteBudget.mutateAsync(selectedBudget.budget_id);
|
||||
NotificationsManager.success("Budget deleted.");
|
||||
NotificationsManager.success(t("budgets.budgetPanel.budgetDeleted"));
|
||||
} catch (error) {
|
||||
console.error("Error deleting budget:", error);
|
||||
if (typeof NotificationsManager.fromBackend === "function") {
|
||||
NotificationsManager.fromBackend("Failed to delete budget");
|
||||
NotificationsManager.fromBackend(t("budgets.budgetPanel.failedToDelete"));
|
||||
} else {
|
||||
NotificationsManager.info("Failed to delete budget");
|
||||
NotificationsManager.info(t("budgets.budgetPanel.failedToDelete"));
|
||||
}
|
||||
} finally {
|
||||
setIsDeleteModalVisible(false);
|
||||
|
|
@ -97,13 +99,13 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
<div className="w-full mx-auto flex-auto overflow-y-auto m-8 p-2">
|
||||
{canModify && (
|
||||
<Button size="sm" variant="primary" className="mb-2" onClick={() => setIsCreateModelVisible(true)}>
|
||||
+ Create Budget
|
||||
{t("budgets.budgetPanel.createBudgetButton")}
|
||||
</Button>
|
||||
)}
|
||||
<TabGroup>
|
||||
<TabList>
|
||||
<Tab>Budgets</Tab>
|
||||
<Tab>Examples</Tab>
|
||||
<Tab>{t("budgets.budgetPanel.tabBudgets")}</Tab>
|
||||
<Tab>{t("budgets.budgetPanel.tabExamples")}</Tab>
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
<TabPanel>
|
||||
|
|
@ -117,14 +119,14 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
/>
|
||||
)}
|
||||
<Card>
|
||||
<Text>Create a budget to assign to customers.</Text>
|
||||
<Text>{t("budgets.budgetPanel.createBudgetDescription")}</Text>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell>Budget ID</TableHeaderCell>
|
||||
<TableHeaderCell>Max Budget</TableHeaderCell>
|
||||
<TableHeaderCell>TPM</TableHeaderCell>
|
||||
<TableHeaderCell>RPM</TableHeaderCell>
|
||||
<TableHeaderCell>{t("budgets.budgetPanel.colBudgetId")}</TableHeaderCell>
|
||||
<TableHeaderCell>{t("budgets.budgetPanel.colMaxBudget")}</TableHeaderCell>
|
||||
<TableHeaderCell>{t("budgets.budgetPanel.colTpm")}</TableHeaderCell>
|
||||
<TableHeaderCell>{t("budgets.budgetPanel.colRpm")}</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
|
||||
|
|
@ -142,13 +144,13 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
<>
|
||||
<TableIconActionButton
|
||||
variant="Edit"
|
||||
tooltipText="Edit budget"
|
||||
tooltipText={t("budgets.budgetPanel.editBudgetTooltip")}
|
||||
onClick={() => handleEditCall(value)}
|
||||
dataTestId="edit-budget-button"
|
||||
/>
|
||||
<TableIconActionButton
|
||||
variant="Delete"
|
||||
tooltipText="Delete budget"
|
||||
tooltipText={t("budgets.budgetPanel.deleteBudgetTooltip")}
|
||||
onClick={() => handleDeleteClick(value)}
|
||||
dataTestId="delete-budget-button"
|
||||
/>
|
||||
|
|
@ -161,14 +163,14 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
</Card>
|
||||
<DeleteResourceModal
|
||||
isOpen={isDeleteModalVisible}
|
||||
title="Delete Budget?"
|
||||
message="Are you sure you want to delete this budget? This action cannot be undone."
|
||||
resourceInformationTitle="Budget Information"
|
||||
title={t("budgets.budgetPanel.deleteTitle")}
|
||||
message={t("budgets.budgetPanel.deleteMessage")}
|
||||
resourceInformationTitle={t("budgets.budgetPanel.budgetInformation")}
|
||||
resourceInformation={[
|
||||
{ label: "Budget ID", value: selectedBudget?.budget_id, code: true },
|
||||
{ label: "Max Budget", value: selectedBudget?.max_budget },
|
||||
{ label: "TPM", value: selectedBudget?.tpm_limit },
|
||||
{ label: "RPM", value: selectedBudget?.rpm_limit },
|
||||
{ label: t("budgets.budgetPanel.colBudgetId"), value: selectedBudget?.budget_id, code: true },
|
||||
{ label: t("budgets.budgetPanel.colMaxBudget"), value: selectedBudget?.max_budget },
|
||||
{ label: t("budgets.budgetPanel.colTpm"), value: selectedBudget?.tpm_limit },
|
||||
{ label: t("budgets.budgetPanel.colRpm"), value: selectedBudget?.rpm_limit },
|
||||
]}
|
||||
onCancel={handleDeleteCancel}
|
||||
onOk={handleDeleteConfirm}
|
||||
|
|
@ -178,12 +180,12 @@ const BudgetPanel: React.FC<BudgetSettingsPageProps> = ({ accessToken }) => {
|
|||
</TabPanel>
|
||||
<TabPanel>
|
||||
<div className="mt-6">
|
||||
<Text className="text-base">How to use budget id</Text>
|
||||
<Text className="text-base">{t("budgets.budgetPanel.howToUseBudgetId")}</Text>
|
||||
<TabGroup>
|
||||
<TabList>
|
||||
<Tab>Assign Budget to Customer</Tab>
|
||||
<Tab>Test it (Curl)</Tab>
|
||||
<Tab>Test it (OpenAI SDK)</Tab>
|
||||
<Tab>{t("budgets.budgetPanel.tabAssignBudget")}</Tab>
|
||||
<Tab>{t("budgets.budgetPanel.tabTestCurl")}</Tab>
|
||||
<Tab>{t("budgets.budgetPanel.tabTestSdk")}</Tab>
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
<TabPanel>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { TextInput, Accordion, AccordionHeader, AccordionBody } from "@tremor/react";
|
||||
import { Button as Button2, Modal, Form, InputNumber, Select } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useUpdateBudget } from "@/app/(dashboard)/hooks/budgets/useBudgets";
|
||||
import { budgetItem } from "./budget_panel";
|
||||
import NotificationsManager from "../molecules/notifications_manager";
|
||||
|
|
@ -11,6 +12,7 @@ interface EditBudgetModalProps {
|
|||
existingBudget: budgetItem;
|
||||
}
|
||||
const EditBudgetModal: React.FC<EditBudgetModalProps> = ({ isModalVisible, setIsModalVisible, existingBudget }) => {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const updateBudget = useUpdateBudget();
|
||||
|
||||
|
|
@ -30,19 +32,26 @@ const EditBudgetModal: React.FC<EditBudgetModalProps> = ({ isModalVisible, setIs
|
|||
|
||||
const handleUpdate = async (formValues: Record<string, any>) => {
|
||||
try {
|
||||
NotificationsManager.info("Making API Call");
|
||||
NotificationsManager.info(t("budgets.editBudgetModal.makingApiCall"));
|
||||
await updateBudget.mutateAsync(formValues);
|
||||
NotificationsManager.success("Budget Updated");
|
||||
NotificationsManager.success(t("budgets.editBudgetModal.budgetUpdated"));
|
||||
form.resetFields();
|
||||
setIsModalVisible(false);
|
||||
} catch (error) {
|
||||
console.error("Error updating the budget:", error);
|
||||
NotificationsManager.fromBackend(`Error updating the budget: ${error}`);
|
||||
NotificationsManager.fromBackend(t("budgets.editBudgetModal.errorUpdating", { error }));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal title="Edit Budget" open={isModalVisible} width={800} footer={null} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Modal
|
||||
title={t("budgets.editBudgetModal.title")}
|
||||
open={isModalVisible}
|
||||
width={800}
|
||||
footer={null}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
>
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={handleUpdate}
|
||||
|
|
@ -52,29 +61,41 @@ const EditBudgetModal: React.FC<EditBudgetModalProps> = ({ isModalVisible, setIs
|
|||
initialValues={existingBudget}
|
||||
>
|
||||
<>
|
||||
<Form.Item label="Budget ID" name="budget_id" help="Budget ID cannot be changed after creation">
|
||||
<Form.Item
|
||||
label={t("budgets.editBudgetModal.budgetIdLabel")}
|
||||
name="budget_id"
|
||||
help={t("budgets.editBudgetModal.budgetIdHelp")}
|
||||
>
|
||||
<TextInput placeholder="" disabled={true} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Max Tokens per minute" name="tpm_limit" help="Default is model limit.">
|
||||
<Form.Item
|
||||
label={t("budgets.editBudgetModal.tpmLimitLabel")}
|
||||
name="tpm_limit"
|
||||
help={t("budgets.editBudgetModal.defaultModelLimit")}
|
||||
>
|
||||
<InputNumber step={1} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
<Form.Item label="Max Requests per minute" name="rpm_limit" help="Default is model limit.">
|
||||
<Form.Item
|
||||
label={t("budgets.editBudgetModal.rpmLimitLabel")}
|
||||
name="rpm_limit"
|
||||
help={t("budgets.editBudgetModal.defaultModelLimit")}
|
||||
>
|
||||
<InputNumber step={1} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
|
||||
<Accordion className="mt-20 mb-8">
|
||||
<AccordionHeader>
|
||||
<b>Optional Settings</b>
|
||||
<b>{t("budgets.editBudgetModal.optionalSettings")}</b>
|
||||
</AccordionHeader>
|
||||
<AccordionBody>
|
||||
<Form.Item label="Max Budget (USD)" name="max_budget">
|
||||
<Form.Item label={t("budgets.editBudgetModal.maxBudgetLabel")} name="max_budget">
|
||||
<InputNumber step={0.01} precision={2} width={200} />
|
||||
</Form.Item>
|
||||
<Form.Item className="mt-8" label="Reset Budget" name="budget_duration">
|
||||
<Form.Item className="mt-8" label={t("budgets.editBudgetModal.resetBudgetLabel")} name="budget_duration">
|
||||
<Select defaultValue={null} placeholder="n/a">
|
||||
<Select.Option value="24h">daily</Select.Option>
|
||||
<Select.Option value="7d">weekly</Select.Option>
|
||||
<Select.Option value="30d">monthly</Select.Option>
|
||||
<Select.Option value="24h">{t("budgets.editBudgetModal.daily")}</Select.Option>
|
||||
<Select.Option value="7d">{t("budgets.editBudgetModal.weekly")}</Select.Option>
|
||||
<Select.Option value="30d">{t("budgets.editBudgetModal.monthly")}</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</AccordionBody>
|
||||
|
|
@ -82,7 +103,7 @@ const EditBudgetModal: React.FC<EditBudgetModalProps> = ({ isModalVisible, setIs
|
|||
</>
|
||||
|
||||
<div style={{ textAlign: "right", marginTop: "10px" }}>
|
||||
<Button2 htmlType="submit">Save</Button2>
|
||||
<Button2 htmlType="submit">{t("common.save")}</Button2>
|
||||
</div>
|
||||
</Form>
|
||||
</Modal>
|
||||
|
|
|
|||
|
|
@ -7616,5 +7616,64 @@
|
|||
"needHelp": "Need Help?",
|
||||
"reuseCredentials": "Reuse Credentials"
|
||||
}
|
||||
},
|
||||
"budgets": {
|
||||
"budgetModal": {
|
||||
"title": "Create Budget",
|
||||
"makingApiCall": "Making API Call",
|
||||
"budgetCreated": "Budget Created",
|
||||
"errorCreating": "Error creating the budget: {{error}}",
|
||||
"budgetIdLabel": "Budget ID",
|
||||
"budgetIdRequired": "Please input a human-friendly name for the budget",
|
||||
"budgetIdHelp": "A human-friendly name for the budget",
|
||||
"tpmLimitLabel": "Max Tokens per minute",
|
||||
"rpmLimitLabel": "Max Requests per minute",
|
||||
"defaultModelLimit": "Default is model limit.",
|
||||
"optionalSettings": "Optional Settings",
|
||||
"maxBudgetLabel": "Max Budget (USD)",
|
||||
"resetBudgetLabel": "Reset Budget",
|
||||
"daily": "daily",
|
||||
"weekly": "weekly",
|
||||
"monthly": "monthly",
|
||||
"createBudgetButton": "Create Budget"
|
||||
},
|
||||
"budgetPanel": {
|
||||
"budgetDeleted": "Budget deleted.",
|
||||
"failedToDelete": "Failed to delete budget",
|
||||
"createBudgetButton": "+ Create Budget",
|
||||
"tabBudgets": "Budgets",
|
||||
"tabExamples": "Examples",
|
||||
"createBudgetDescription": "Create a budget to assign to customers.",
|
||||
"colBudgetId": "Budget ID",
|
||||
"colMaxBudget": "Max Budget",
|
||||
"colTpm": "TPM",
|
||||
"colRpm": "RPM",
|
||||
"editBudgetTooltip": "Edit budget",
|
||||
"deleteBudgetTooltip": "Delete budget",
|
||||
"deleteTitle": "Delete Budget?",
|
||||
"deleteMessage": "Are you sure you want to delete this budget? This action cannot be undone.",
|
||||
"budgetInformation": "Budget Information",
|
||||
"howToUseBudgetId": "How to use budget id",
|
||||
"tabAssignBudget": "Assign Budget to Customer",
|
||||
"tabTestCurl": "Test it (Curl)",
|
||||
"tabTestSdk": "Test it (OpenAI SDK)"
|
||||
},
|
||||
"editBudgetModal": {
|
||||
"title": "Edit Budget",
|
||||
"makingApiCall": "Making API Call",
|
||||
"budgetUpdated": "Budget Updated",
|
||||
"errorUpdating": "Error updating the budget: {{error}}",
|
||||
"budgetIdLabel": "Budget ID",
|
||||
"budgetIdHelp": "Budget ID cannot be changed after creation",
|
||||
"tpmLimitLabel": "Max Tokens per minute",
|
||||
"rpmLimitLabel": "Max Requests per minute",
|
||||
"defaultModelLimit": "Default is model limit.",
|
||||
"optionalSettings": "Optional Settings",
|
||||
"maxBudgetLabel": "Max Budget (USD)",
|
||||
"resetBudgetLabel": "Reset Budget",
|
||||
"daily": "daily",
|
||||
"weekly": "weekly",
|
||||
"monthly": "monthly"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7616,5 +7616,64 @@
|
|||
"needHelp": "需要帮助?",
|
||||
"reuseCredentials": "复用凭据"
|
||||
}
|
||||
},
|
||||
"budgets": {
|
||||
"budgetModal": {
|
||||
"title": "创建预算",
|
||||
"makingApiCall": "正在调用 API",
|
||||
"budgetCreated": "预算已创建",
|
||||
"errorCreating": "创建预算时出错:{{error}}",
|
||||
"budgetIdLabel": "预算 ID",
|
||||
"budgetIdRequired": "请输入一个易于识别的预算名称",
|
||||
"budgetIdHelp": "一个易于识别的预算名称",
|
||||
"tpmLimitLabel": "每分钟最大 Token 数",
|
||||
"rpmLimitLabel": "每分钟最大请求数",
|
||||
"defaultModelLimit": "默认使用模型限制。",
|
||||
"optionalSettings": "可选设置",
|
||||
"maxBudgetLabel": "最大预算(美元)",
|
||||
"resetBudgetLabel": "重置预算",
|
||||
"daily": "每天",
|
||||
"weekly": "每周",
|
||||
"monthly": "每月",
|
||||
"createBudgetButton": "创建预算"
|
||||
},
|
||||
"budgetPanel": {
|
||||
"budgetDeleted": "预算已删除。",
|
||||
"failedToDelete": "删除预算失败",
|
||||
"createBudgetButton": "+ 创建预算",
|
||||
"tabBudgets": "预算",
|
||||
"tabExamples": "示例",
|
||||
"createBudgetDescription": "创建预算以分配给客户。",
|
||||
"colBudgetId": "预算 ID",
|
||||
"colMaxBudget": "最大预算",
|
||||
"colTpm": "TPM",
|
||||
"colRpm": "RPM",
|
||||
"editBudgetTooltip": "编辑预算",
|
||||
"deleteBudgetTooltip": "删除预算",
|
||||
"deleteTitle": "删除预算?",
|
||||
"deleteMessage": "确定要删除此预算吗?此操作不可撤销。",
|
||||
"budgetInformation": "预算信息",
|
||||
"howToUseBudgetId": "如何使用预算 ID",
|
||||
"tabAssignBudget": "分配预算给客户",
|
||||
"tabTestCurl": "测试(Curl)",
|
||||
"tabTestSdk": "测试(OpenAI SDK)"
|
||||
},
|
||||
"editBudgetModal": {
|
||||
"title": "编辑预算",
|
||||
"makingApiCall": "正在调用 API",
|
||||
"budgetUpdated": "预算已更新",
|
||||
"errorUpdating": "更新预算时出错:{{error}}",
|
||||
"budgetIdLabel": "预算 ID",
|
||||
"budgetIdHelp": "预算 ID 创建后不可更改",
|
||||
"tpmLimitLabel": "每分钟最大 Token 数",
|
||||
"rpmLimitLabel": "每分钟最大请求数",
|
||||
"defaultModelLimit": "默认使用模型限制。",
|
||||
"optionalSettings": "可选设置",
|
||||
"maxBudgetLabel": "最大预算(美元)",
|
||||
"resetBudgetLabel": "重置预算",
|
||||
"daily": "每天",
|
||||
"weekly": "每周",
|
||||
"monthly": "每月"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue