mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
feat(ui): i18n for team batch 1
This commit is contained in:
parent
1927d31e42
commit
4882456643
5 changed files with 232 additions and 57 deletions
|
|
@ -1,6 +1,7 @@
|
|||
import { Text, TextInput } from "@tremor/react";
|
||||
import { Button as AntButton, Form, Modal, Select } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import NumericalInput from "../shared/numerical_input";
|
||||
import BudgetDurationDropdown from "../common_components/budget_duration_dropdown";
|
||||
|
||||
|
|
@ -48,6 +49,7 @@ const MemberModal = <T extends BaseMember>({
|
|||
mode,
|
||||
config,
|
||||
}: MemberModalProps<T>) => {
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
||||
|
|
@ -135,7 +137,7 @@ const MemberModal = <T extends BaseMember>({
|
|||
step={field.step || 1}
|
||||
min={field.min || 0}
|
||||
style={{ width: "100%" }}
|
||||
placeholder={field.placeholder || "Enter a numerical value"}
|
||||
placeholder={field.placeholder || t("teamPage.editMembership.numericalPlaceholder")}
|
||||
/>
|
||||
);
|
||||
case "select":
|
||||
|
|
@ -152,7 +154,7 @@ const MemberModal = <T extends BaseMember>({
|
|||
return (
|
||||
<Select
|
||||
mode="multiple"
|
||||
placeholder={field.placeholder || "Select options"}
|
||||
placeholder={field.placeholder || t("teamPage.editMembership.selectOptionsPlaceholder")}
|
||||
options={field.options}
|
||||
allowClear
|
||||
/>
|
||||
|
|
@ -166,7 +168,10 @@ const MemberModal = <T extends BaseMember>({
|
|||
|
||||
return (
|
||||
<Modal
|
||||
title={config.title || (mode === "add" ? "Add Member" : "Edit Member")}
|
||||
title={
|
||||
config.title ||
|
||||
(mode === "add" ? t("teamPage.editMembership.addMemberTitle") : t("teamPage.editMembership.editMemberTitle"))
|
||||
}
|
||||
open={visible}
|
||||
width={1000}
|
||||
footer={null}
|
||||
|
|
@ -175,39 +180,41 @@ const MemberModal = <T extends BaseMember>({
|
|||
<Form form={form} onFinish={handleSubmit} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} labelAlign="left">
|
||||
{config.showEmail && (
|
||||
<Form.Item
|
||||
label="Email"
|
||||
label={t("teamPage.editMembership.emailLabel")}
|
||||
name="user_email"
|
||||
className="mb-4"
|
||||
rules={[{ type: "email", message: "Please enter a valid email!" }]}
|
||||
rules={[{ type: "email", message: t("teamPage.editMembership.emailInvalid") }]}
|
||||
>
|
||||
<TextInput placeholder="user@example.com" />
|
||||
<TextInput placeholder={t("teamPage.editMembership.emailPlaceholder")} />
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{config.showEmail && config.showUserId && (
|
||||
<div className="text-center mb-4">
|
||||
<Text>OR</Text>
|
||||
<Text>{t("teamPage.editMembership.orDivider")}</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{config.showUserId && (
|
||||
<Form.Item label="User ID" name="user_id" className="mb-4">
|
||||
<TextInput placeholder="user_123" />
|
||||
<Form.Item label={t("teamPage.editMembership.userIdLabel")} name="user_id" className="mb-4">
|
||||
<TextInput placeholder={t("teamPage.editMembership.userIdPlaceholder")} />
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Form.Item
|
||||
label={
|
||||
<div className="flex items-center gap-2">
|
||||
<span>Role</span>
|
||||
<span>{t("teamPage.editMembership.roleLabel")}</span>
|
||||
{mode === "edit" && initialData && (
|
||||
<span className="text-gray-500 text-sm">(Current: {getRoleLabel(initialData.role)})</span>
|
||||
<span className="text-gray-500 text-sm">
|
||||
{t("teamPage.editMembership.roleCurrent", { role: getRoleLabel(initialData.role) })}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
name="role"
|
||||
className="mb-4"
|
||||
rules={[{ required: true, message: "Please select a role!" }]}
|
||||
rules={[{ required: true, message: t("teamPage.editMembership.roleRequired") }]}
|
||||
>
|
||||
<Select>
|
||||
{mode === "edit" && initialData
|
||||
|
|
@ -237,10 +244,16 @@ const MemberModal = <T extends BaseMember>({
|
|||
|
||||
<div className="text-right mt-6">
|
||||
<AntButton onClick={onCancel} className="mr-2" disabled={isSubmitting}>
|
||||
Cancel
|
||||
{t("common.cancel")}
|
||||
</AntButton>
|
||||
<AntButton type="default" htmlType="submit" loading={isSubmitting}>
|
||||
{mode === "add" ? (isSubmitting ? "Adding..." : "Add Member") : isSubmitting ? "Saving..." : "Save Changes"}
|
||||
{mode === "add"
|
||||
? isSubmitting
|
||||
? t("teamPage.editMembership.addingButton")
|
||||
: t("teamPage.editMembership.addMemberButton")
|
||||
: isSubmitting
|
||||
? t("teamPage.editMembership.savingButton")
|
||||
: t("teamPage.editMembership.saveChangesButton")}
|
||||
</AntButton>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { Select, Tooltip, Divider } from "antd";
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Button, Card, TextInput } from "@tremor/react";
|
||||
import { PlusIcon, TrashIcon, CogIcon, BanIcon } from "@heroicons/react/outline";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { callbackInfo, callback_map, mapDisplayToInternalNames } from "../callback_info_helpers";
|
||||
import NumericalInput from "../shared/numerical_input";
|
||||
|
||||
|
|
@ -29,6 +30,8 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
disabledCallbacks = [],
|
||||
onDisabledCallbacksChange,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
// Get callbacks that support team and key logging
|
||||
const supportedCallbacks = Object.entries(callbackInfo)
|
||||
.filter(([_, info]) => info.supports_key_team_logging)
|
||||
|
|
@ -110,7 +113,9 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<div className="w-3 h-3 bg-blue-100 rounded-full flex items-center justify-center">
|
||||
<div className="w-1.5 h-1.5 bg-blue-500 rounded-full"></div>
|
||||
</div>
|
||||
<span className="text-sm font-medium text-gray-700">Integration Parameters</span>
|
||||
<span className="text-sm font-medium text-gray-700">
|
||||
{t("teamPage.loggingSettings.integrationParametersTitle")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4">
|
||||
{Object.entries(dynamicParams).map(([paramName, paramType]) => (
|
||||
|
|
@ -122,16 +127,18 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
</Tooltip>
|
||||
{paramType === "password" && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800">
|
||||
Sensitive
|
||||
{t("teamPage.loggingSettings.sensitiveBadge")}
|
||||
</span>
|
||||
)}
|
||||
{paramType === "number" && (
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800">
|
||||
Number
|
||||
{t("teamPage.loggingSettings.numberBadge")}
|
||||
</span>
|
||||
)}
|
||||
</label>
|
||||
{paramType === "number" && <span className="text-xs text-gray-500">Value must be between 0 and 1</span>}
|
||||
{paramType === "number" && (
|
||||
<span className="text-xs text-gray-500">{t("teamPage.loggingSettings.numberRangeHint")}</span>
|
||||
)}
|
||||
{paramType === "number" ? (
|
||||
<NumericalInput
|
||||
step={0.01}
|
||||
|
|
@ -161,17 +168,21 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<BanIcon className="w-5 h-5 text-red-500" />
|
||||
<span className="text-base font-semibold text-gray-800">Disabled Callbacks</span>
|
||||
<Tooltip title="Select callbacks to disable for this key. Disabled callbacks will not receive any logging data.">
|
||||
<span className="text-base font-semibold text-gray-800">
|
||||
{t("teamPage.loggingSettings.disabledCallbacksTitle")}
|
||||
</span>
|
||||
<Tooltip title={t("teamPage.loggingSettings.disabledCallbacksTooltip")}>
|
||||
<InfoCircleOutlined className="text-gray-400 cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-700">Disabled Callbacks</label>
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
{t("teamPage.loggingSettings.disabledCallbacksLabel")}
|
||||
</label>
|
||||
<Select
|
||||
mode="multiple"
|
||||
placeholder="Select callbacks to disable"
|
||||
placeholder={t("teamPage.loggingSettings.disabledCallbacksPlaceholder")}
|
||||
value={disabledCallbacks}
|
||||
onChange={handleDisabledCallbacksChange}
|
||||
style={{ width: "100%" }}
|
||||
|
|
@ -210,9 +221,7 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
);
|
||||
})}
|
||||
</Select>
|
||||
<div className="text-xs text-gray-500">
|
||||
Select callbacks that should be disabled for this key. These callbacks will not receive any logging data.
|
||||
</div>
|
||||
<div className="text-xs text-gray-500">{t("teamPage.loggingSettings.disabledCallbacksHelp")}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -222,8 +231,10 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center space-x-2">
|
||||
<CogIcon className="w-5 h-5 text-blue-500" />
|
||||
<span className="text-base font-semibold text-gray-800">Logging Integrations</span>
|
||||
<Tooltip title="Configure callback logging integrations for this team.">
|
||||
<span className="text-base font-semibold text-gray-800">
|
||||
{t("teamPage.loggingSettings.loggingIntegrationsTitle")}
|
||||
</span>
|
||||
<Tooltip title={t("teamPage.loggingSettings.loggingIntegrationsTooltip")}>
|
||||
<InfoCircleOutlined className="text-gray-400 cursor-help" />
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
@ -235,7 +246,7 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
className="hover:border-blue-400 hover:text-blue-500"
|
||||
type="button"
|
||||
>
|
||||
Add Integration
|
||||
{t("teamPage.loggingSettings.addIntegrationButton")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -256,7 +267,10 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<div className="flex justify-between items-start mb-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
{logoUrl && <img src={logoUrl} alt={callbackDisplayName} className="w-5 h-5 object-contain" />}
|
||||
<span className="text-sm font-medium">{callbackDisplayName || "New Integration"} Configuration</span>
|
||||
<span className="text-sm font-medium">
|
||||
{callbackDisplayName || t("teamPage.loggingSettings.newIntegrationFallback")}{" "}
|
||||
{t("teamPage.loggingSettings.configurationSuffix")}
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="light"
|
||||
|
|
@ -267,16 +281,18 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
className="hover:bg-red-50"
|
||||
type="button"
|
||||
>
|
||||
Remove
|
||||
{t("teamPage.loggingSettings.removeButton")}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-700">Integration Type</label>
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
{t("teamPage.loggingSettings.integrationTypeLabel")}
|
||||
</label>
|
||||
<Select
|
||||
value={callbackDisplayName}
|
||||
placeholder="Select integration"
|
||||
placeholder={t("teamPage.loggingSettings.selectIntegrationPlaceholder")}
|
||||
onChange={(value) => updateLoggingConfig(index, "callback_name", value)}
|
||||
className="w-full"
|
||||
optionLabelProp="label"
|
||||
|
|
@ -317,7 +333,9 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium text-gray-700">Event Type</label>
|
||||
<label className="text-sm font-medium text-gray-700">
|
||||
{t("teamPage.loggingSettings.eventTypeLabel")}
|
||||
</label>
|
||||
<Select
|
||||
value={config.callback_type}
|
||||
onChange={(value) => updateLoggingConfig(index, "callback_type", value)}
|
||||
|
|
@ -326,19 +344,19 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
<Option value="success">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-2 h-2 bg-green-500 rounded-full"></div>
|
||||
<span>Success Only</span>
|
||||
<span>{t("teamPage.loggingSettings.successOnly")}</span>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value="failure">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-2 h-2 bg-red-500 rounded-full"></div>
|
||||
<span>Failure Only</span>
|
||||
<span>{t("teamPage.loggingSettings.failureOnly")}</span>
|
||||
</div>
|
||||
</Option>
|
||||
<Option value="success_and_failure">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-2 h-2 bg-blue-500 rounded-full"></div>
|
||||
<span>Success & Failure</span>
|
||||
<span>{t("teamPage.loggingSettings.successAndFailure")}</span>
|
||||
</div>
|
||||
</Option>
|
||||
</Select>
|
||||
|
|
@ -355,8 +373,8 @@ const LoggingSettings: React.FC<LoggingSettingsProps> = ({
|
|||
{value.length === 0 && (
|
||||
<div className="text-center py-12 text-gray-500 border-2 border-dashed border-gray-200 rounded-lg bg-gray-50/50">
|
||||
<CogIcon className="w-12 h-12 text-gray-300 mb-3 mx-auto" />
|
||||
<div className="text-base font-medium mb-1">No logging integrations configured</div>
|
||||
<div className="text-sm text-gray-400">Click "Add Integration" to configure logging for this team</div>
|
||||
<div className="text-base font-medium mb-1">{t("teamPage.loggingSettings.emptyTitle")}</div>
|
||||
<div className="text-sm text-gray-400">{t("teamPage.loggingSettings.emptySubtitle")}</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { formatNumberWithCommas } from "@/utils/dataUtils";
|
|||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMyTeamMember } from "./useMyTeamMember";
|
||||
|
||||
interface MyUserTabProps {
|
||||
|
|
@ -23,18 +24,19 @@ const formatNumber = (value: number | null | undefined, digits = 4): string => {
|
|||
return formatNumberWithCommas(value, digits);
|
||||
};
|
||||
|
||||
const formatRateLimit = (value: number | null | undefined): string => {
|
||||
if (value === null || value === undefined) return "Unlimited";
|
||||
const formatRateLimit = (value: number | null | undefined, unlimitedLabel: string): string => {
|
||||
if (value === null || value === undefined) return unlimitedLabel;
|
||||
return formatNumberWithCommas(value, 0);
|
||||
};
|
||||
|
||||
export default function MyUserTab({ teamId }: MyUserTabProps) {
|
||||
const { t } = useTranslation();
|
||||
const { data, isLoading, error } = useMyTeamMember(teamId);
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<Card>
|
||||
<Typography.Text type="secondary">Loading your membership info…</Typography.Text>
|
||||
<Typography.Text type="secondary">{t("teamPage.myUserTab.loadingText")}</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -43,7 +45,7 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
return (
|
||||
<Card>
|
||||
<Typography.Text type="danger">
|
||||
{error instanceof Error ? error.message : "Failed to load your membership info for this team."}
|
||||
{error instanceof Error ? error.message : t("teamPage.myUserTab.errorFallback")}
|
||||
</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
|
|
@ -52,9 +54,7 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
if (!data) {
|
||||
return (
|
||||
<Card>
|
||||
<Typography.Text type="secondary">
|
||||
No membership info available for the current user in this team.
|
||||
</Typography.Text>
|
||||
<Typography.Text type="secondary">{t("teamPage.myUserTab.noDataText")}</Typography.Text>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
|
@ -68,12 +68,14 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
const budgetReset = formatBudgetReset(budgetTable?.budget_reset_at);
|
||||
const allowedModels = budgetTable?.allowed_models ?? null;
|
||||
|
||||
const unlimitedLabel = t("teamPage.myUserTab.unlimited");
|
||||
|
||||
return (
|
||||
<Space direction="vertical" size="middle" style={{ width: "100%" }}>
|
||||
<Card>
|
||||
<Row gutter={[24, 16]}>
|
||||
<Col xs={24} sm={12} md={8}>
|
||||
<Typography.Text type="secondary">User</Typography.Text>
|
||||
<Typography.Text type="secondary">{t("teamPage.myUserTab.userLabel")}</Typography.Text>
|
||||
<div style={{ marginTop: 4 }}>
|
||||
<Typography.Text strong>{data.user_email || data.user_id}</Typography.Text>
|
||||
</div>
|
||||
|
|
@ -82,7 +84,7 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
</Typography.Text>
|
||||
</Col>
|
||||
<Col xs={24} sm={12} md={8}>
|
||||
<Typography.Text type="secondary">Team Role</Typography.Text>
|
||||
<Typography.Text type="secondary">{t("teamPage.myUserTab.teamRoleLabel")}</Typography.Text>
|
||||
<div style={{ marginTop: 4 }}>
|
||||
<Tag color={data.role === "admin" ? "blue" : "default"}>{data.role || "user"}</Tag>
|
||||
</div>
|
||||
|
|
@ -94,20 +96,24 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
<Col xs={24} md={12}>
|
||||
<Card>
|
||||
{labelWithTooltip(
|
||||
"Current Cycle Spend (USD)",
|
||||
"Spend for the current budget cycle. Resets to $0 when the budget window rolls over.",
|
||||
t("teamPage.myUserTab.currentCycleSpendLabel"),
|
||||
t("teamPage.myUserTab.currentCycleSpendTooltip"),
|
||||
)}
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Typography.Title level={3} style={{ margin: 0 }}>
|
||||
${formatNumber(spend, 4)}
|
||||
</Typography.Title>
|
||||
<Typography.Text type="secondary">
|
||||
of {maxBudget === null ? "Unlimited" : `$${formatNumber(maxBudget, 4)}`}
|
||||
{t("teamPage.myUserTab.ofBudget", {
|
||||
budget: maxBudget === null ? unlimitedLabel : `$${formatNumber(maxBudget, 4)}`,
|
||||
})}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
{budgetReset && (
|
||||
<div style={{ marginTop: 4 }}>
|
||||
<Typography.Text type="secondary">Resets {budgetReset}</Typography.Text>
|
||||
<Typography.Text type="secondary">
|
||||
{t("teamPage.myUserTab.resetsAt", { when: budgetReset })}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
|
@ -115,18 +121,22 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
|
||||
<Col xs={24} md={12}>
|
||||
<Card>
|
||||
{labelWithTooltip("Rate Limits", "Your per-member rate limits within this team.")}
|
||||
{labelWithTooltip(t("teamPage.myUserTab.rateLimitsLabel"), t("teamPage.myUserTab.rateLimitsTooltip"))}
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Typography.Text>TPM: {formatRateLimit(tpmLimit)}</Typography.Text>
|
||||
<Typography.Text>
|
||||
{t("teamPage.myUserTab.tpmValue", { value: formatRateLimit(tpmLimit, unlimitedLabel) })}
|
||||
</Typography.Text>
|
||||
<br />
|
||||
<Typography.Text>RPM: {formatRateLimit(rpmLimit)}</Typography.Text>
|
||||
<Typography.Text>
|
||||
{t("teamPage.myUserTab.rpmValue", { value: formatRateLimit(rpmLimit, unlimitedLabel) })}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
<Col xs={24} md={12}>
|
||||
<Card>
|
||||
{labelWithTooltip("Total Spend (USD)", "Cumulative spend across all budget cycles within this team.")}
|
||||
{labelWithTooltip(t("teamPage.myUserTab.totalSpendLabel"), t("teamPage.myUserTab.totalSpendTooltip"))}
|
||||
<div style={{ marginTop: 8 }}>
|
||||
<Typography.Title level={4} style={{ margin: 0 }}>
|
||||
${formatNumber(totalSpend, 4)}
|
||||
|
|
@ -137,7 +147,7 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
|
||||
<Col xs={24} md={12}>
|
||||
<Card>
|
||||
{labelWithTooltip("Model Scope", "Models you can access within this team.")}
|
||||
{labelWithTooltip(t("teamPage.myUserTab.modelScopeLabel"), t("teamPage.myUserTab.modelScopeTooltip"))}
|
||||
<div style={{ marginTop: 8 }}>
|
||||
{allowedModels && allowedModels.length > 0 ? (
|
||||
<Space wrap>
|
||||
|
|
@ -146,7 +156,7 @@ export default function MyUserTab({ teamId }: MyUserTabProps) {
|
|||
))}
|
||||
</Space>
|
||||
) : (
|
||||
<Typography.Text>All Team Models</Typography.Text>
|
||||
<Typography.Text>{t("teamPage.myUserTab.allTeamModels")}</Typography.Text>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
|||
|
|
@ -6181,5 +6181,72 @@
|
|||
"descriptionPlaceholder": "Describe what this agent does...",
|
||||
"credentialFieldRequired": "Please enter {{label}}"
|
||||
}
|
||||
},
|
||||
"teamPage": {
|
||||
"editMembership": {
|
||||
"emailLabel": "Email",
|
||||
"emailPlaceholder": "user@example.com",
|
||||
"emailInvalid": "Please enter a valid email!",
|
||||
"orDivider": "OR",
|
||||
"userIdLabel": "User ID",
|
||||
"userIdPlaceholder": "user_123",
|
||||
"roleLabel": "Role",
|
||||
"roleCurrent": "(Current: {{role}})",
|
||||
"roleRequired": "Please select a role!",
|
||||
"numericalPlaceholder": "Enter a numerical value",
|
||||
"selectOptionsPlaceholder": "Select options",
|
||||
"addMemberTitle": "Add Member",
|
||||
"editMemberTitle": "Edit Member",
|
||||
"addingButton": "Adding...",
|
||||
"addMemberButton": "Add Member",
|
||||
"savingButton": "Saving...",
|
||||
"saveChangesButton": "Save Changes"
|
||||
},
|
||||
"loggingSettings": {
|
||||
"disabledCallbacksTitle": "Disabled Callbacks",
|
||||
"disabledCallbacksTooltip": "Select callbacks to disable for this key. Disabled callbacks will not receive any logging data.",
|
||||
"disabledCallbacksLabel": "Disabled Callbacks",
|
||||
"disabledCallbacksPlaceholder": "Select callbacks to disable",
|
||||
"disabledCallbacksHelp": "Select callbacks that should be disabled for this key. These callbacks will not receive any logging data.",
|
||||
"loggingIntegrationsTitle": "Logging Integrations",
|
||||
"loggingIntegrationsTooltip": "Configure callback logging integrations for this team.",
|
||||
"addIntegrationButton": "Add Integration",
|
||||
"integrationParametersTitle": "Integration Parameters",
|
||||
"sensitiveBadge": "Sensitive",
|
||||
"numberBadge": "Number",
|
||||
"numberRangeHint": "Value must be between 0 and 1",
|
||||
"newIntegrationFallback": "New Integration",
|
||||
"configurationSuffix": "Configuration",
|
||||
"removeButton": "Remove",
|
||||
"integrationTypeLabel": "Integration Type",
|
||||
"selectIntegrationPlaceholder": "Select integration",
|
||||
"eventTypeLabel": "Event Type",
|
||||
"successOnly": "Success Only",
|
||||
"failureOnly": "Failure Only",
|
||||
"successAndFailure": "Success & Failure",
|
||||
"emptyTitle": "No logging integrations configured",
|
||||
"emptySubtitle": "Click \"Add Integration\" to configure logging for this team"
|
||||
},
|
||||
"myUserTab": {
|
||||
"loadingText": "Loading your membership info…",
|
||||
"errorFallback": "Failed to load your membership info for this team.",
|
||||
"noDataText": "No membership info available for the current user in this team.",
|
||||
"userLabel": "User",
|
||||
"teamRoleLabel": "Team Role",
|
||||
"currentCycleSpendLabel": "Current Cycle Spend (USD)",
|
||||
"currentCycleSpendTooltip": "Spend for the current budget cycle. Resets to $0 when the budget window rolls over.",
|
||||
"ofBudget": "of {{budget}}",
|
||||
"unlimited": "Unlimited",
|
||||
"resetsAt": "Resets {{when}}",
|
||||
"rateLimitsLabel": "Rate Limits",
|
||||
"rateLimitsTooltip": "Your per-member rate limits within this team.",
|
||||
"tpmValue": "TPM: {{value}}",
|
||||
"rpmValue": "RPM: {{value}}",
|
||||
"totalSpendLabel": "Total Spend (USD)",
|
||||
"totalSpendTooltip": "Cumulative spend across all budget cycles within this team.",
|
||||
"modelScopeLabel": "Model Scope",
|
||||
"modelScopeTooltip": "Models you can access within this team.",
|
||||
"allTeamModels": "All Team Models"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6181,5 +6181,72 @@
|
|||
"descriptionPlaceholder": "描述该 Agent 的功能...",
|
||||
"credentialFieldRequired": "请输入{{label}}"
|
||||
}
|
||||
},
|
||||
"teamPage": {
|
||||
"editMembership": {
|
||||
"emailLabel": "邮箱",
|
||||
"emailPlaceholder": "user@example.com",
|
||||
"emailInvalid": "请输入有效的邮箱地址!",
|
||||
"orDivider": "或",
|
||||
"userIdLabel": "用户 ID",
|
||||
"userIdPlaceholder": "user_123",
|
||||
"roleLabel": "角色",
|
||||
"roleCurrent": "(当前:{{role}})",
|
||||
"roleRequired": "请选择角色!",
|
||||
"numericalPlaceholder": "请输入数值",
|
||||
"selectOptionsPlaceholder": "请选择选项",
|
||||
"addMemberTitle": "添加成员",
|
||||
"editMemberTitle": "编辑成员",
|
||||
"addingButton": "添加中...",
|
||||
"addMemberButton": "添加成员",
|
||||
"savingButton": "保存中...",
|
||||
"saveChangesButton": "保存更改"
|
||||
},
|
||||
"loggingSettings": {
|
||||
"disabledCallbacksTitle": "已禁用的回调",
|
||||
"disabledCallbacksTooltip": "选择要为此密钥禁用的回调。已禁用的回调不会收到任何日志数据。",
|
||||
"disabledCallbacksLabel": "已禁用的回调",
|
||||
"disabledCallbacksPlaceholder": "选择要禁用的回调",
|
||||
"disabledCallbacksHelp": "选择应为此密钥禁用的回调。这些回调不会收到任何日志数据。",
|
||||
"loggingIntegrationsTitle": "日志集成",
|
||||
"loggingIntegrationsTooltip": "为此团队配置回调日志集成。",
|
||||
"addIntegrationButton": "添加集成",
|
||||
"integrationParametersTitle": "集成参数",
|
||||
"sensitiveBadge": "敏感",
|
||||
"numberBadge": "数值",
|
||||
"numberRangeHint": "值必须在 0 到 1 之间",
|
||||
"newIntegrationFallback": "新集成",
|
||||
"configurationSuffix": "配置",
|
||||
"removeButton": "移除",
|
||||
"integrationTypeLabel": "集成类型",
|
||||
"selectIntegrationPlaceholder": "选择集成",
|
||||
"eventTypeLabel": "事件类型",
|
||||
"successOnly": "仅成功",
|
||||
"failureOnly": "仅失败",
|
||||
"successAndFailure": "成功与失败",
|
||||
"emptyTitle": "未配置日志集成",
|
||||
"emptySubtitle": "点击「添加集成」为此团队配置日志"
|
||||
},
|
||||
"myUserTab": {
|
||||
"loadingText": "正在加载您的成员信息…",
|
||||
"errorFallback": "加载您在此团队的成员信息失败。",
|
||||
"noDataText": "当前用户在此团队中没有可用的成员信息。",
|
||||
"userLabel": "用户",
|
||||
"teamRoleLabel": "团队角色",
|
||||
"currentCycleSpendLabel": "当前周期花费(USD)",
|
||||
"currentCycleSpendTooltip": "当前预算周期的花费。预算窗口滚动时将重置为 $0。",
|
||||
"ofBudget": "共 {{budget}}",
|
||||
"unlimited": "不限",
|
||||
"resetsAt": "重置于 {{when}}",
|
||||
"rateLimitsLabel": "速率限制",
|
||||
"rateLimitsTooltip": "您在此团队中的每成员速率限制。",
|
||||
"tpmValue": "TPM:{{value}}",
|
||||
"rpmValue": "RPM:{{value}}",
|
||||
"totalSpendLabel": "累计花费(USD)",
|
||||
"totalSpendTooltip": "此团队所有预算周期的累计花费。",
|
||||
"modelScopeLabel": "模型范围",
|
||||
"modelScopeTooltip": "您在此团队中可访问的模型。",
|
||||
"allTeamModels": "所有团队模型"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue