diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_export_utils.ts b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_export_utils.ts index cee52cd1024..c23e1586814 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_export_utils.ts +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/multi_export_utils.ts @@ -1,3 +1,4 @@ +import i18n from "@/lib/i18n"; import { CostEstimateResponse } from "../types"; import { formatNumberWithCommas } from "@/utils/dataUtils"; import { MultiModelResult } from "./types"; @@ -16,44 +17,45 @@ const formatRequestsForExport = (value: number | null | undefined): string => { }; const generateModelSection = (result: CostEstimateResponse): string => { + const t = i18n.t.bind(i18n); return `

${result.model} ${result.provider ? `(${result.provider})` : ""}

- +
-

Input Tokens per Request: ${formatRequestsForExport(result.input_tokens)}

-

Output Tokens per Request: ${formatRequestsForExport(result.output_tokens)}

- ${result.num_requests_per_day ? `

Requests per Day: ${formatRequestsForExport(result.num_requests_per_day)}

` : ""} - ${result.num_requests_per_month ? `

Requests per Month: ${formatRequestsForExport(result.num_requests_per_month)}

` : ""} +

${t("costTracking.multiExportUtils.inputTokensPerRequest")} ${formatRequestsForExport(result.input_tokens)}

+

${t("costTracking.multiExportUtils.outputTokensPerRequest")} ${formatRequestsForExport(result.output_tokens)}

+ ${result.num_requests_per_day ? `

${t("costTracking.multiExportUtils.requestsPerDay")} ${formatRequestsForExport(result.num_requests_per_day)}

` : ""} + ${result.num_requests_per_month ? `

${t("costTracking.multiExportUtils.requestsPerMonth")} ${formatRequestsForExport(result.num_requests_per_month)}

` : ""}
- - - ${result.daily_cost !== null ? "" : ""} - ${result.monthly_cost !== null ? "" : ""} + + + ${result.daily_cost !== null ? `` : ""} + ${result.monthly_cost !== null ? `` : ""} - + ${result.daily_cost !== null ? `` : ""} ${result.monthly_cost !== null ? `` : ""} - + ${result.daily_cost !== null ? `` : ""} ${result.monthly_cost !== null ? `` : ""} - + ${result.daily_cost !== null ? `` : ""} ${result.monthly_cost !== null ? `` : ""} - + ${result.daily_cost !== null ? `` : ""} ${result.monthly_cost !== null ? `` : ""} @@ -64,9 +66,10 @@ const generateModelSection = (result: CostEstimateResponse): string => { }; export const exportMultiToPDF = (multiResult: MultiModelResult): void => { + const t = i18n.t.bind(i18n); const printWindow = window.open("", "_blank"); if (!printWindow) { - alert("Please allow popups to export PDF"); + alert(t("costTracking.multiExportUtils.popupBlockedAlert")); return; } @@ -193,22 +196,22 @@ export const exportMultiToPDF = (multiResult: MultiModelResult): void => { -

LLM Cost Estimate Report

-

${modelCount} model${modelCount !== 1 ? "s" : ""} configured

- +

${t("costTracking.multiExportUtils.reportTitle")}

+

${t("costTracking.multiExportUtils.modelCount", { count: modelCount })}

+
-

Combined Totals

+

${t("costTracking.multiExportUtils.combinedTotals")}

-
Total Per Request
+
${t("costTracking.multiExportUtils.totalPerRequest")}
${formatCostForExport(multiResult.totals.cost_per_request)}
-
Total Daily
+
${t("costTracking.multiExportUtils.totalDaily")}
${formatCostForExport(multiResult.totals.daily_cost)}
-
Total Monthly
+
${t("costTracking.multiExportUtils.totalMonthly")}
${formatCostForExport(multiResult.totals.monthly_cost)}
@@ -217,15 +220,15 @@ export const exportMultiToPDF = (multiResult: MultiModelResult): void => { ? `
-
Margin/Request
+
${t("costTracking.multiExportUtils.marginPerRequest")}
${formatCostForExport(multiResult.totals.margin_per_request)}
-
Daily Margin
+
${t("costTracking.multiExportUtils.dailyMargin")}
${formatCostForExport(multiResult.totals.daily_margin)}
-
Monthly Margin
+
${t("costTracking.multiExportUtils.monthlyMargin")}
${formatCostForExport(multiResult.totals.monthly_margin)}
@@ -234,11 +237,11 @@ export const exportMultiToPDF = (multiResult: MultiModelResult): void => { }
-

Model Breakdown

+

${t("costTracking.multiExportUtils.modelBreakdown")}

${validEntries.map((e) => generateModelSection(e.result!)).join("")} @@ -252,36 +255,39 @@ export const exportMultiToPDF = (multiResult: MultiModelResult): void => { }; export const exportMultiToCSV = (multiResult: MultiModelResult): void => { + const t = i18n.t.bind(i18n); const validEntries = multiResult.entries.filter((e) => e.result !== null); - const rows: string[][] = [["LLM Multi-Model Cost Estimate Report"], ["Generated", new Date().toLocaleString()], [""]]; + const rows: string[][] = [ + [t("costTracking.multiExportUtils.csvReportTitle")], + [t("costTracking.multiExportUtils.csvGenerated"), new Date().toLocaleString()], + [""], + ]; - // Summary section rows.push( - ["COMBINED TOTALS"], - ["Total Per Request", multiResult.totals.cost_per_request.toString()], - ["Total Daily", multiResult.totals.daily_cost?.toString() || "-"], - ["Total Monthly", multiResult.totals.monthly_cost?.toString() || "-"], - ["Margin Per Request", multiResult.totals.margin_per_request.toString()], - ["Daily Margin", multiResult.totals.daily_margin?.toString() || "-"], - ["Monthly Margin", multiResult.totals.monthly_margin?.toString() || "-"], + [t("costTracking.multiExportUtils.csvCombinedTotals")], + [t("costTracking.multiExportUtils.csvTotalPerRequest"), multiResult.totals.cost_per_request.toString()], + [t("costTracking.multiExportUtils.csvTotalDaily"), multiResult.totals.daily_cost?.toString() || "-"], + [t("costTracking.multiExportUtils.csvTotalMonthly"), multiResult.totals.monthly_cost?.toString() || "-"], + [t("costTracking.multiExportUtils.csvMarginPerRequest"), multiResult.totals.margin_per_request.toString()], + [t("costTracking.multiExportUtils.csvDailyMargin"), multiResult.totals.daily_margin?.toString() || "-"], + [t("costTracking.multiExportUtils.csvMonthlyMargin"), multiResult.totals.monthly_margin?.toString() || "-"], [""], ); - // Summary table header rows.push([ - "Model", - "Provider", - "Input Tokens", - "Output Tokens", - "Requests/Day", - "Requests/Month", - "Cost/Request", - "Daily Cost", - "Monthly Cost", - "Input Cost/Req", - "Output Cost/Req", - "Margin/Req", + t("costTracking.multiExportUtils.csvColModel"), + t("costTracking.multiExportUtils.csvColProvider"), + t("costTracking.multiExportUtils.csvColInputTokens"), + t("costTracking.multiExportUtils.csvColOutputTokens"), + t("costTracking.multiExportUtils.csvColRequestsPerDay"), + t("costTracking.multiExportUtils.csvColRequestsPerMonth"), + t("costTracking.multiExportUtils.csvColCostPerRequest"), + t("costTracking.multiExportUtils.csvColDailyCost"), + t("costTracking.multiExportUtils.csvColMonthlyCost"), + t("costTracking.multiExportUtils.csvColInputCostPerReq"), + t("costTracking.multiExportUtils.csvColOutputCostPerReq"), + t("costTracking.multiExportUtils.csvColMarginPerReq"), ]); // Add each model's data diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/provider_margin_table.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/provider_margin_table.tsx index bee7a1219d2..00ab630b0e1 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/provider_margin_table.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/provider_margin_table.tsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; +import { useTranslation } from "react-i18next"; import { TextInput, Icon, Text } from "@tremor/react"; import { TrashIcon, PencilAltIcon, CheckIcon, XIcon } from "@heroicons/react/outline"; import { SimpleTable } from "../common_components/simple_table"; @@ -21,6 +22,7 @@ const ProviderMarginTable: React.FC = ({ onMarginChange, onRemoveProvider, }) => { + const { t } = useTranslation(); const [editingProvider, setEditingProvider] = useState(null); const [editPercentage, setEditPercentage] = useState(""); const [editFixedAmount, setEditFixedAmount] = useState(""); @@ -106,12 +108,12 @@ const ProviderMarginTable: React.FC = ({ data={data} columns={[ { - header: "Provider", + header: t("costTracking.providerMarginTable.colProvider"), cell: (row) => { if (row.provider === "global") { return (
- Global (All Providers) + {t("costTracking.providerMarginTable.globalProviderLabel")}
); } @@ -121,7 +123,7 @@ const ProviderMarginTable: React.FC = ({ {logo && ( {`${displayName} handleImageError(e, displayName)} /> @@ -132,7 +134,7 @@ const ProviderMarginTable: React.FC = ({ }, }, { - header: "Margin", + header: t("costTracking.providerMarginTable.colMargin"), cell: (row) => (
{editingProvider === row.provider ? ( @@ -184,7 +186,7 @@ const ProviderMarginTable: React.FC = ({ width: "350px", }, { - header: "Actions", + header: t("costTracking.providerMarginTable.colActions"), cell: (row) => { const displayName = row.provider === "global" ? "Global" : getProviderDisplayInfo(row.provider).displayName; return ( @@ -200,7 +202,7 @@ const ProviderMarginTable: React.FC = ({ }, ]} getRowKey={(row) => row.provider} - emptyMessage="No provider margins configured" + emptyMessage={t("costTracking.providerMarginTable.emptyMessage")} /> ); }; diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/use_discount_config.ts b/ui/litellm-dashboard/src/components/CostTrackingSettings/use_discount_config.ts index 5ed00ce1cbc..ae11e0f1f69 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/use_discount_config.ts +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/use_discount_config.ts @@ -1,4 +1,5 @@ import { useState, useCallback } from "react"; +import { useTranslation } from "react-i18next"; import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking"; import NotificationsManager from "../molecules/notifications_manager"; import { DiscountConfig } from "./types"; @@ -20,6 +21,7 @@ export interface UseDiscountConfigReturn { } export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseDiscountConfigReturn { + const { t } = useTranslation(); const [discountConfig, setDiscountConfig] = useState({}); const fetchDiscountConfig = useCallback(async () => { @@ -43,7 +45,7 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD } } catch (error) { console.error("Error fetching discount config:", error); - NotificationsManager.fromBackend("Failed to fetch discount configuration"); + NotificationsManager.fromBackend(t("costTracking.useDiscountConfig.fetchFailed")); } }, [accessToken]); @@ -63,7 +65,7 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD }); if (response.ok) { - NotificationsManager.success("Discount configuration updated successfully"); + NotificationsManager.success(t("costTracking.useDiscountConfig.updateSuccess")); await fetchDiscountConfig(); } else { const errorData = await response.json(); @@ -72,7 +74,7 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD } } catch (error) { console.error("Error updating discount config:", error); - NotificationsManager.fromBackend("Failed to update discount configuration"); + NotificationsManager.fromBackend(t("costTracking.useDiscountConfig.updateFailed")); } }, [accessToken, fetchDiscountConfig], @@ -81,26 +83,28 @@ export function useDiscountConfig({ accessToken }: UseDiscountConfigProps): UseD const handleAddProvider = useCallback( async (selectedProvider: string | undefined, newDiscount: string): Promise => { if (!selectedProvider || !newDiscount) { - NotificationsManager.fromBackend("Please select a provider and enter discount percentage"); + NotificationsManager.fromBackend(t("costTracking.useDiscountConfig.selectProviderAndDiscount")); return false; } const percentageValue = parseFloat(newDiscount); if (isNaN(percentageValue) || percentageValue < 0 || percentageValue > 100) { - NotificationsManager.fromBackend("Discount must be between 0% and 100%"); + NotificationsManager.fromBackend(t("costTracking.useDiscountConfig.invalidDiscountRange")); return false; } const providerValue = getProviderBackendValue(selectedProvider); if (!providerValue) { - NotificationsManager.fromBackend("Invalid provider selected"); + NotificationsManager.fromBackend(t("costTracking.useDiscountConfig.invalidProvider")); return false; } if (discountConfig[providerValue]) { NotificationsManager.fromBackend( - `Discount for ${Providers[selectedProvider as keyof typeof Providers]} already exists. Edit it in the table above.`, + t("costTracking.useDiscountConfig.discountAlreadyExists", { + providerName: Providers[selectedProvider as keyof typeof Providers], + }), ); return false; } diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/use_margin_config.ts b/ui/litellm-dashboard/src/components/CostTrackingSettings/use_margin_config.ts index 0af70b070d5..2a999b6eb35 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/use_margin_config.ts +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/use_margin_config.ts @@ -1,4 +1,5 @@ import { useState, useCallback } from "react"; +import { useTranslation } from "react-i18next"; import { getProxyBaseUrl, getGlobalLitellmHeaderName } from "@/components/networking"; import NotificationsManager from "../molecules/notifications_manager"; import { MarginConfig } from "./types"; @@ -30,6 +31,7 @@ export interface AddMarginParams { } export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMarginConfigReturn { + const { t } = useTranslation(); const [marginConfig, setMarginConfig] = useState({}); const fetchMarginConfig = useCallback(async () => { @@ -53,7 +55,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi } } catch (error) { console.error("Error fetching margin config:", error); - NotificationsManager.fromBackend("Failed to fetch margin configuration"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.fetchFailed")); } }, [accessToken]); @@ -73,7 +75,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi }); if (response.ok) { - NotificationsManager.success("Margin configuration updated successfully"); + NotificationsManager.success(t("costTracking.useMarginConfig.updateSuccess")); await fetchMarginConfig(); } else { const errorData = await response.json(); @@ -82,7 +84,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi } } catch (error) { console.error("Error updating margin config:", error); - NotificationsManager.fromBackend("Failed to update margin configuration"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.updateFailed")); } }, [accessToken, fetchMarginConfig], @@ -93,7 +95,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi const { selectedProvider, marginType, percentageValue, fixedAmountValue } = params; if (!selectedProvider) { - NotificationsManager.fromBackend("Please select a provider"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.selectProvider")); return false; } @@ -103,7 +105,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi } else { const backendValue = getProviderBackendValue(selectedProvider); if (!backendValue) { - NotificationsManager.fromBackend("Invalid provider selected"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.invalidProvider")); return false; } providerValue = backendValue; @@ -112,7 +114,7 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi if (marginConfig[providerValue]) { const displayName = providerValue === "global" ? "Global" : Providers[selectedProvider as keyof typeof Providers]; - NotificationsManager.fromBackend(`Margin for ${displayName} already exists. Edit it in the table above.`); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.marginAlreadyExists", { displayName })); return false; } @@ -120,14 +122,14 @@ export function useMarginConfig({ accessToken }: UseMarginConfigProps): UseMargi if (marginType === "percentage") { const percentValue = parseFloat(percentageValue); if (isNaN(percentValue) || percentValue < 0 || percentValue > 1000) { - NotificationsManager.fromBackend("Percentage must be between 0% and 1000%"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.invalidPercentageRange")); return false; } marginValue = percentValue / 100; } else { const fixedValue = parseFloat(fixedAmountValue); if (isNaN(fixedValue) || fixedValue < 0) { - NotificationsManager.fromBackend("Fixed amount must be non-negative"); + NotificationsManager.fromBackend(t("costTracking.useMarginConfig.invalidFixedAmount")); return false; } marginValue = { fixed_amount: fixedValue }; diff --git a/ui/litellm-dashboard/src/locales/en.json b/ui/litellm-dashboard/src/locales/en.json index 98fad82ba01..2e5282dd6f6 100644 --- a/ui/litellm-dashboard/src/locales/en.json +++ b/ui/litellm-dashboard/src/locales/en.json @@ -4793,6 +4793,80 @@ "multiExportDropdown": { "exportAsPdf": "Export as PDF", "exportAsCsv": "Export as CSV" + }, + "multiExportUtils": { + "popupBlockedAlert": "Please allow popups to export PDF", + "reportTitle": "LLM Cost Estimate Report", + "modelCount_one": "{{count}} model configured", + "modelCount_other": "{{count}} models configured", + "combinedTotals": "Combined Totals", + "totalPerRequest": "Total Per Request", + "totalDaily": "Total Daily", + "totalMonthly": "Total Monthly", + "marginPerRequest": "Margin/Request", + "dailyMargin": "Daily Margin", + "monthlyMargin": "Monthly Margin", + "modelBreakdown": "Model Breakdown", + "generatedOn": "Generated by LiteLLM Pricing Calculator on {{date}}", + "inputTokensPerRequest": "Input Tokens per Request:", + "outputTokensPerRequest": "Output Tokens per Request:", + "requestsPerDay": "Requests per Day:", + "requestsPerMonth": "Requests per Month:", + "colCostType": "Cost Type", + "colPerRequest": "Per Request", + "colDaily": "Daily", + "colMonthly": "Monthly", + "inputCost": "Input Cost", + "outputCost": "Output Cost", + "marginFee": "Margin/Fee", + "csvReportTitle": "LLM Multi-Model Cost Estimate Report", + "csvGenerated": "Generated", + "csvCombinedTotals": "COMBINED TOTALS", + "csvTotalPerRequest": "Total Per Request", + "csvTotalDaily": "Total Daily", + "csvTotalMonthly": "Total Monthly", + "csvMarginPerRequest": "Margin Per Request", + "csvDailyMargin": "Daily Margin", + "csvMonthlyMargin": "Monthly Margin", + "csvColModel": "Model", + "csvColProvider": "Provider", + "csvColInputTokens": "Input Tokens", + "csvColOutputTokens": "Output Tokens", + "csvColRequestsPerDay": "Requests/Day", + "csvColRequestsPerMonth": "Requests/Month", + "csvColCostPerRequest": "Cost/Request", + "csvColDailyCost": "Daily Cost", + "csvColMonthlyCost": "Monthly Cost", + "csvColInputCostPerReq": "Input Cost/Req", + "csvColOutputCostPerReq": "Output Cost/Req", + "csvColMarginPerReq": "Margin/Req" + }, + "providerMarginTable": { + "colProvider": "Provider", + "colMargin": "Margin", + "colActions": "Actions", + "globalProviderLabel": "Global (All Providers)", + "logoAlt": "{{displayName}} logo", + "emptyMessage": "No provider margins configured" + }, + "useDiscountConfig": { + "fetchFailed": "Failed to fetch discount configuration", + "updateFailed": "Failed to update discount configuration", + "updateSuccess": "Discount configuration updated successfully", + "selectProviderAndDiscount": "Please select a provider and enter discount percentage", + "invalidDiscountRange": "Discount must be between 0% and 100%", + "invalidProvider": "Invalid provider selected", + "discountAlreadyExists": "Discount for {{providerName}} already exists. Edit it in the table above." + }, + "useMarginConfig": { + "fetchFailed": "Failed to fetch margin configuration", + "updateFailed": "Failed to update margin configuration", + "updateSuccess": "Margin configuration updated successfully", + "selectProvider": "Please select a provider", + "invalidProvider": "Invalid provider selected", + "marginAlreadyExists": "Margin for {{displayName}} already exists. Edit it in the table above.", + "invalidPercentageRange": "Percentage must be between 0% and 1000%", + "invalidFixedAmount": "Fixed amount must be non-negative" } } } diff --git a/ui/litellm-dashboard/src/locales/zh-CN.json b/ui/litellm-dashboard/src/locales/zh-CN.json index 965c1fdf322..25043fb1ab0 100644 --- a/ui/litellm-dashboard/src/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/locales/zh-CN.json @@ -4793,6 +4793,80 @@ "multiExportDropdown": { "exportAsPdf": "导出为 PDF", "exportAsCsv": "导出为 CSV" + }, + "multiExportUtils": { + "popupBlockedAlert": "请允许弹出窗口以导出 PDF", + "reportTitle": "LLM 成本估算报告", + "modelCount_one": "已配置 {{count}} 个模型", + "modelCount_other": "已配置 {{count}} 个模型", + "combinedTotals": "合计", + "totalPerRequest": "每次请求总计", + "totalDaily": "每日总计", + "totalMonthly": "每月总计", + "marginPerRequest": "利润率/请求", + "dailyMargin": "每日利润率", + "monthlyMargin": "每月利润率", + "modelBreakdown": "模型明细", + "generatedOn": "由 LiteLLM 价格计算器生成于 {{date}}", + "inputTokensPerRequest": "每次请求输入 Token:", + "outputTokensPerRequest": "每次请求输出 Token:", + "requestsPerDay": "每日请求数:", + "requestsPerMonth": "每月请求数:", + "colCostType": "成本类型", + "colPerRequest": "每次请求", + "colDaily": "每日", + "colMonthly": "每月", + "inputCost": "输入成本", + "outputCost": "输出成本", + "marginFee": "利润率/费用", + "csvReportTitle": "LLM 多模型成本估算报告", + "csvGenerated": "生成时间", + "csvCombinedTotals": "合计", + "csvTotalPerRequest": "每次请求总计", + "csvTotalDaily": "每日总计", + "csvTotalMonthly": "每月总计", + "csvMarginPerRequest": "每次请求利润率", + "csvDailyMargin": "每日利润率", + "csvMonthlyMargin": "每月利润率", + "csvColModel": "模型", + "csvColProvider": "提供商", + "csvColInputTokens": "输入 Token", + "csvColOutputTokens": "输出 Token", + "csvColRequestsPerDay": "请求数/天", + "csvColRequestsPerMonth": "请求数/月", + "csvColCostPerRequest": "成本/请求", + "csvColDailyCost": "每日成本", + "csvColMonthlyCost": "每月成本", + "csvColInputCostPerReq": "输入成本/请求", + "csvColOutputCostPerReq": "输出成本/请求", + "csvColMarginPerReq": "利润率/请求" + }, + "providerMarginTable": { + "colProvider": "提供商", + "colMargin": "利润率", + "colActions": "操作", + "globalProviderLabel": "全局(所有提供商)", + "logoAlt": "{{displayName}} 徽标", + "emptyMessage": "未配置提供商利润率" + }, + "useDiscountConfig": { + "fetchFailed": "获取折扣配置失败", + "updateFailed": "更新折扣配置失败", + "updateSuccess": "折扣配置已成功更新", + "selectProviderAndDiscount": "请选择提供商并输入折扣百分比", + "invalidDiscountRange": "折扣必须在 0% 到 100% 之间", + "invalidProvider": "所选提供商无效", + "discountAlreadyExists": "{{providerName}} 的折扣已存在,请在上方表格中编辑。" + }, + "useMarginConfig": { + "fetchFailed": "获取利润率配置失败", + "updateFailed": "更新利润率配置失败", + "updateSuccess": "利润率配置已成功更新", + "selectProvider": "请选择提供商", + "invalidProvider": "所选提供商无效", + "marginAlreadyExists": "{{displayName}} 的利润率已存在,请在上方表格中编辑。", + "invalidPercentageRange": "百分比必须在 0% 到 1000% 之间", + "invalidFixedAmount": "固定金额不能为负数" } } }
Cost TypePer RequestDailyMonthly${t("costTracking.multiExportUtils.colCostType")}${t("costTracking.multiExportUtils.colPerRequest")}${t("costTracking.multiExportUtils.colDaily")}${t("costTracking.multiExportUtils.colMonthly")}
Input Cost${t("costTracking.multiExportUtils.inputCost")} ${formatCostForExport(result.input_cost_per_request)}${formatCostForExport(result.daily_input_cost)}${formatCostForExport(result.monthly_input_cost)}
Output Cost${t("costTracking.multiExportUtils.outputCost")} ${formatCostForExport(result.output_cost_per_request)}${formatCostForExport(result.daily_output_cost)}${formatCostForExport(result.monthly_output_cost)}
Margin/Fee${t("costTracking.multiExportUtils.marginFee")} ${formatCostForExport(result.margin_cost_per_request)}${formatCostForExport(result.daily_margin_cost)}${formatCostForExport(result.monthly_margin_cost)}
Total${t("common.total")} ${formatCostForExport(result.cost_per_request)}${formatCostForExport(result.daily_cost)}${formatCostForExport(result.monthly_cost)}