diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/add_margin_form.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/add_margin_form.tsx index a3900eab257..abb36afba46 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/add_margin_form.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/add_margin_form.tsx @@ -2,6 +2,7 @@ import React from "react"; import { TextInput, Button } from "@tremor/react"; import { Select as AntdSelect, Form, Tooltip, Radio } from "antd"; import { InfoCircleOutlined } from "@ant-design/icons"; +import { useTranslation } from "react-i18next"; import { Providers, provider_map, providerLogoMap } from "../provider_info_helpers"; import { MarginConfig } from "./types"; import { handleImageError } from "./provider_display_helpers"; @@ -31,22 +32,24 @@ const AddMarginForm: React.FC = ({ onFixedAmountChange, onAddProvider, }) => { + const { t } = useTranslation(); + return (
- Provider - + {t("costTracking.addMarginForm.providerLabel")} + } - rules={[{ required: true, message: "Please select a provider" }]} + rules={[{ required: true, message: t("costTracking.addMarginForm.providerRequired") }]} > = ({ .includes(input.toLowerCase()) } > - +
- Global (All Providers) + {t("costTracking.addMarginForm.globalOption")}
{Object.entries(Providers).map(([providerEnum, providerDisplayName]) => { @@ -89,17 +92,17 @@ const AddMarginForm: React.FC = ({ - Margin Type - + {t("costTracking.addMarginForm.marginTypeLabel")} + } - rules={[{ required: true, message: "Please select a margin type" }]} + rules={[{ required: true, message: t("costTracking.addMarginForm.marginTypeRequired") }]} > onMarginTypeChange(e.target.value)} className="w-full"> - Percentage-based - Fixed Amount + {t("costTracking.addMarginForm.percentageBased")} + {t("costTracking.addMarginForm.fixedAmount")} @@ -107,22 +110,22 @@ const AddMarginForm: React.FC = ({ - Margin Percentage - + {t("costTracking.addMarginForm.marginPercentageLabel")} + } rules={[ - { required: true, message: "Please enter a margin percentage" }, + { required: true, message: t("costTracking.addMarginForm.percentageRequired") }, { validator: (_, value) => { if (!value) { - return Promise.reject(new Error("Please enter a margin percentage")); + return Promise.reject(new Error(t("costTracking.addMarginForm.percentageRequired"))); } const numValue = parseFloat(value); if (isNaN(numValue) || numValue < 0 || numValue > 1000) { - return Promise.reject(new Error("Percentage must be between 0 and 1000")); + return Promise.reject(new Error(t("costTracking.addMarginForm.percentageRangeError"))); } return Promise.resolve(); }, @@ -145,22 +148,22 @@ const AddMarginForm: React.FC = ({ - Fixed Margin Amount - + {t("costTracking.addMarginForm.fixedAmountLabel")} + } rules={[ - { required: true, message: "Please enter a fixed amount" }, + { required: true, message: t("costTracking.addMarginForm.fixedAmountRequired") }, { validator: (_, value) => { if (!value) { - return Promise.reject(new Error("Please enter a fixed amount")); + return Promise.reject(new Error(t("costTracking.addMarginForm.fixedAmountRequired"))); } const numValue = parseFloat(value); if (isNaN(numValue) || numValue < 0) { - return Promise.reject(new Error("Fixed amount must be non-negative")); + return Promise.reject(new Error(t("costTracking.addMarginForm.fixedAmountNonNegative"))); } return Promise.resolve(); }, @@ -189,7 +192,7 @@ const AddMarginForm: React.FC = ({ (marginType === "fixed" && !fixedAmountValue) } > - Add Provider Margin + {t("costTracking.addMarginForm.addButton")}
diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/add_provider_form.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/add_provider_form.tsx index bb11acb83aa..c1686a604b3 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/add_provider_form.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/add_provider_form.tsx @@ -2,6 +2,7 @@ import React from "react"; import { TextInput, Button } from "@tremor/react"; import { Select as AntdSelect, Form, Tooltip } from "antd"; import { InfoCircleOutlined } from "@ant-design/icons"; +import { useTranslation } from "react-i18next"; import { Providers, provider_map, providerLogoMap } from "../provider_info_helpers"; import { DiscountConfig } from "./types"; import { handleImageError } from "./provider_display_helpers"; @@ -23,22 +24,24 @@ const AddProviderForm: React.FC = ({ onDiscountChange, onAddProvider, }) => { + const { t } = useTranslation(); + return (
- Provider - + {t("costTracking.addProviderForm.providerLabel")} + } - rules={[{ required: true, message: "Please select a provider" }]} + rules={[{ required: true, message: t("costTracking.addProviderForm.providerRequired") }]} > = ({ - Discount Percentage - + {t("costTracking.addProviderForm.discountPercentageLabel")} + } - rules={[{ required: true, message: "Please enter a discount percentage" }]} + rules={[{ required: true, message: t("costTracking.addProviderForm.discountRequired") }]} >
= ({
diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/cost_tracking_settings.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/cost_tracking_settings.tsx index 9dade715cbc..fdf69c8427b 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/cost_tracking_settings.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/cost_tracking_settings.tsx @@ -13,6 +13,7 @@ import { TabPanel, } from "@tremor/react"; import { Modal, Form } from "antd"; +import { useTranslation } from "react-i18next"; import { CostTrackingSettingsProps } from "./types"; import ProviderDiscountTable from "./provider_discount_table"; import AddProviderForm from "./add_provider_form"; @@ -32,6 +33,7 @@ const DOCS_LINKS = [ ]; const CostTrackingSettings: React.FC = ({ userID, userRole, accessToken }) => { + const { t } = useTranslation(); const [selectedProvider, setSelectedProvider] = useState(undefined); const [newDiscount, setNewDiscount] = useState(""); const [isFetching, setIsFetching] = useState(true); @@ -106,12 +108,12 @@ const CostTrackingSettings: React.FC = ({ userID, use const handleRemoveProvider = async (provider: string, providerDisplayName: string) => { modal.confirm({ - title: "Remove Provider Discount", + title: t("costTracking.costTrackingSettings.removeDiscountTitle"), icon: , - content: `Are you sure you want to remove the discount for ${providerDisplayName}?`, - okText: "Remove", + content: t("costTracking.costTrackingSettings.removeDiscountContent", { providerDisplayName }), + okText: t("costTracking.costTrackingSettings.removeOkText"), okType: "danger", - cancelText: "Cancel", + cancelText: t("common.cancel"), onOk: () => removeProvider(provider), }); }; @@ -143,12 +145,12 @@ const CostTrackingSettings: React.FC = ({ userID, use const handleRemoveMargin = async (provider: string, providerDisplayName: string) => { modal.confirm({ - title: "Remove Provider Margin", + title: t("costTracking.costTrackingSettings.removeMarginTitle"), icon: , - content: `Are you sure you want to remove the margin for ${providerDisplayName}?`, - okText: "Remove", + content: t("costTracking.costTrackingSettings.removeMarginContent", { providerDisplayName }), + okText: t("costTracking.costTrackingSettings.removeOkText"), okType: "danger", - cancelText: "Cancel", + cancelText: t("common.cancel"), onOk: () => removeMargin(provider), }); }; @@ -165,12 +167,10 @@ const CostTrackingSettings: React.FC = ({ userID, use
- Cost Tracking Settings + {t("costTracking.costTrackingSettings.pageTitle")}
- - Configure cost discounts and margins for different LLM providers. Changes are saved automatically. - + {t("costTracking.costTrackingSettings.pageSubtitle")}
@@ -181,27 +181,31 @@ const CostTrackingSettings: React.FC = ({ userID, use
- Provider Discounts + + {t("costTracking.costTrackingSettings.providerDiscountsTitle")} + - Apply percentage-based discounts to reduce costs for specific providers + {t("costTracking.costTrackingSettings.providerDiscountsSubtitle")}
- Discounts - Test It + {t("costTracking.costTrackingSettings.discountsTab")} + {t("costTracking.costTrackingSettings.testItTab")}
- +
{isFetching ? (
- Loading configuration... + {t("common.loading")}
) : Object.keys(discountConfig).length > 0 ? ( = ({ userID, use d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> - No provider discounts configured + + {t("costTracking.costTrackingSettings.noDiscountsConfigured")} + - Click "Add Provider Discount" to get started + {t("costTracking.costTrackingSettings.noDiscountsHint")}
)} @@ -248,20 +254,24 @@ const CostTrackingSettings: React.FC = ({ userID, use
- Fee/Price Margin + + {t("costTracking.costTrackingSettings.feePriceMarginTitle")} + - Add fees or margins to LLM costs for internal billing and cost recovery + {t("costTracking.costTrackingSettings.feePriceMarginSubtitle")}
- +
{isFetching ? (
- Loading configuration... + {t("common.loading")}
) : Object.keys(marginConfig).length > 0 ? ( = ({ userID, use d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /> - No provider margins configured - Click "Add Provider Margin" to get started + + {t("costTracking.costTrackingSettings.noMarginsConfigured")} + + + {t("costTracking.costTrackingSettings.noMarginsHint")} +
)}
@@ -297,9 +311,11 @@ const CostTrackingSettings: React.FC = ({ userID, use
- Pricing Calculator + + {t("costTracking.costTrackingSettings.pricingCalculatorTitle")} + - Estimate LLM costs based on expected token usage and request volume + {t("costTracking.costTrackingSettings.pricingCalculatorSubtitle")}
@@ -314,7 +330,9 @@ const CostTrackingSettings: React.FC = ({ userID, use -

Add Provider Discount

+

+ {t("costTracking.costTrackingSettings.addDiscountModalTitle")} +

} open={isModalVisible} @@ -329,8 +347,7 @@ const CostTrackingSettings: React.FC = ({ userID, use >
- Select a provider and set its discount percentage. Enter a value between 0% and 100% (e.g., 5 for a 5% - discount). + {t("costTracking.costTrackingSettings.addDiscountModalDesc")}
= ({ userID, use -

Add Provider Margin

+

+ {t("costTracking.costTrackingSettings.addMarginModalTitle")} +

} open={isMarginModalVisible} @@ -363,8 +382,7 @@ const CostTrackingSettings: React.FC = ({ userID, use >
- Select a provider (or "Global" for all providers) and configure the margin. You can use - percentage-based or fixed amount. + {t("costTracking.costTrackingSettings.addMarginModalDesc")} { + const { t } = useTranslation(); const [responseCost, setResponseCost] = useState(""); const [discountAmount, setDiscountAmount] = useState(""); @@ -28,30 +30,30 @@ const HowItWorks: React.FC = () => { return (
- Cost Calculation + + {t("costTracking.howItWorks.costCalculationTitle")} + - Discounts are applied to provider costs:{" "} + {t("costTracking.howItWorks.costCalculationDesc")}{" "} final_cost = base_cost × (1 - discount%/100)
- Example - - A 5% discount on a $10.00 request results in: $10.00 × (1 - 0.05) = $9.50 - + {t("costTracking.howItWorks.exampleTitle")} + {t("costTracking.howItWorks.exampleDesc")}
- Valid Range - Discount percentages must be between 0% and 100% + {t("costTracking.howItWorks.validRangeTitle")} + {t("costTracking.howItWorks.validRangeDesc")}
- Validating Discounts - - Make a test request and check the response headers to verify discounts are applied: + + {t("costTracking.howItWorks.validatingDiscountsTitle")} + {t("costTracking.howItWorks.validatingDiscountsDesc")} { "messages": [{"role": "user", "content": "Hello"}] }'`} /> - Look for these headers in the response: + {t("costTracking.howItWorks.lookForHeaders")}
x-litellm-response-cost - Final cost after discount + {t("costTracking.howItWorks.headerResponseCost")}
x-litellm-response-cost-original - Original cost before discount + {t("costTracking.howItWorks.headerOriginalCost")}
x-litellm-response-cost-discount-amount - Amount discounted + {t("costTracking.howItWorks.headerDiscountAmount")}
- Discount Calculator - - Enter values from your response headers to verify the discount: + + {t("costTracking.howItWorks.discountCalculatorTitle")} + {t("costTracking.howItWorks.discountCalculatorDesc")}
{
{ {calculatedDiscount && (
- Calculated Results + + {t("costTracking.howItWorks.calculatedResultsTitle")} +
- Original Cost: + {t("costTracking.howItWorks.originalCostLabel")} ${calculatedDiscount.originalCost}
- Final Cost: + {t("costTracking.howItWorks.finalCostLabel")} ${calculatedDiscount.finalCost}
- Discount Amount: + {t("costTracking.howItWorks.discountAmountResultLabel")} ${calculatedDiscount.discountAmount}
- Discount Applied: + + {t("costTracking.howItWorks.discountAppliedLabel")} + {calculatedDiscount.discountPercentage}%
diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/index.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/index.tsx index 9b355e55c1c..10cafa0780f 100644 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/index.tsx +++ b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/index.tsx @@ -1,6 +1,7 @@ import React, { useState, useCallback } from "react"; import { Table, Select, InputNumber, Button, Radio } from "antd"; import { DeleteOutlined, PlusOutlined } from "@ant-design/icons"; +import { useTranslation } from "react-i18next"; import { PricingCalculatorProps, ModelEntry } from "./types"; import MultiCostResults from "./multi_cost_results"; import { useMultiCostEstimate } from "./use_multi_cost_estimate"; @@ -19,6 +20,7 @@ const createDefaultEntry = (): ModelEntry => ({ }); const PricingCalculator: React.FC = ({ accessToken, models }) => { + const { t } = useTranslation(); const [entries, setEntries] = useState([createDefaultEntry()]); const [timePeriod, setTimePeriod] = useState("month"); const { debouncedFetchForEntry, removeEntry, getMultiModelResult } = useMultiCostEstimate(accessToken); @@ -65,14 +67,14 @@ const PricingCalculator: React.FC = ({ accessToken, mode const columns = [ { - title: "Model", + title: t("costTracking.pricingCalculator.colModel"), dataIndex: "model", key: "model", width: "35%", render: (_: string, record: ModelEntry) => (