mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
feat(ui): i18n for model select components
This commit is contained in:
parent
3cbbffbac4
commit
950a51ff9c
4 changed files with 59 additions and 17 deletions
|
|
@ -3,6 +3,7 @@ import { useOrganization } from "@/app/(dashboard)/hooks/organizations/useOrgani
|
|||
import { useTeam } from "@/app/(dashboard)/hooks/teams/useTeams";
|
||||
import { useCurrentUser } from "@/app/(dashboard)/hooks/users/useCurrentUser";
|
||||
import { Select, Skeleton, Tooltip, type SelectProps } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Organization, Team } from "../networking";
|
||||
import { splitWildcardModels } from "./modelUtils";
|
||||
|
||||
|
|
@ -92,6 +93,7 @@ const filterModels = (
|
|||
};
|
||||
|
||||
export const ModelSelect = (props: ModelSelectProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { teamID, organizationID, options, context, dataTestId, value = [], onChange, style } = props;
|
||||
const { includeUserModels, showAllTeamModelsOption, showAllProxyModelsOverride, includeSpecialOptions } =
|
||||
options || {};
|
||||
|
|
@ -148,13 +150,13 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
...(includeSpecialOptions
|
||||
? [
|
||||
{
|
||||
label: <span>Special Options</span>,
|
||||
title: "Special Options",
|
||||
label: <span>{t("modelSelect.modelSelect.specialOptions")}</span>,
|
||||
title: t("modelSelect.modelSelect.specialOptions"),
|
||||
options: [
|
||||
...(shouldShowAllProxyModels
|
||||
? [
|
||||
{
|
||||
label: <span>All Proxy Models</span>,
|
||||
label: <span>{t("modelSelect.modelSelect.allProxyModels")}</span>,
|
||||
value: MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value,
|
||||
disabled:
|
||||
value.length > 0 &&
|
||||
|
|
@ -166,7 +168,7 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
]
|
||||
: []),
|
||||
{
|
||||
label: <span>No Default Models</span>,
|
||||
label: <span>{t("modelSelect.modelSelect.noDefaultModels")}</span>,
|
||||
value: MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value,
|
||||
disabled:
|
||||
value.length > 0 &&
|
||||
|
|
@ -180,14 +182,16 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
...(wildcard.length > 0
|
||||
? [
|
||||
{
|
||||
label: <span>Wildcard Options</span>,
|
||||
title: "Wildcard Options",
|
||||
label: <span>{t("modelSelect.modelSelect.wildcardOptions")}</span>,
|
||||
title: t("modelSelect.modelSelect.wildcardOptions"),
|
||||
options: wildcard.map((model) => {
|
||||
const provider = model.replace("/*", "");
|
||||
const capitalizedProvider = provider.charAt(0).toUpperCase() + provider.slice(1);
|
||||
|
||||
return {
|
||||
label: <span>{`All ${capitalizedProvider} models`}</span>,
|
||||
label: (
|
||||
<span>{t("modelSelect.modelSelect.allProviderModels", { provider: capitalizedProvider })}</span>
|
||||
),
|
||||
value: model,
|
||||
disabled: hasSpecialOptionSelected,
|
||||
};
|
||||
|
|
@ -196,8 +200,8 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
]
|
||||
: []),
|
||||
{
|
||||
label: <span>Models</span>,
|
||||
title: "Models",
|
||||
label: <span>{t("modelSelect.modelSelect.models")}</span>,
|
||||
title: t("modelSelect.modelSelect.models"),
|
||||
options: regular.map((model) => ({
|
||||
label: <span>{model}</span>,
|
||||
value: model,
|
||||
|
|
@ -206,7 +210,7 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
},
|
||||
]}
|
||||
mode="multiple"
|
||||
placeholder="Select Models"
|
||||
placeholder={t("modelSelect.modelSelect.selectModels")}
|
||||
allowClear
|
||||
maxTagCount="responsive"
|
||||
maxTagPlaceholder={(omittedValues) => (
|
||||
|
|
@ -214,7 +218,7 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
styles={{ root: { pointerEvents: "none" } }}
|
||||
title={omittedValues.map(({ value }) => value).join(", ")}
|
||||
>
|
||||
<span>+{omittedValues.length} more</span>
|
||||
<span>{t("modelSelect.modelSelect.moreModels", { count: omittedValues.length })}</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { LoadingOutlined } from "@ant-design/icons";
|
|||
import { useDebouncedState } from "@tanstack/react-pacer/debouncer";
|
||||
import { Select, Space, Typography } from "antd";
|
||||
import { useMemo, useState, type UIEvent } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
|
|
@ -22,12 +23,13 @@ const DEBOUNCE_MS = 300;
|
|||
export const PaginatedModelSelect = ({
|
||||
value,
|
||||
onChange,
|
||||
placeholder = "Select a model",
|
||||
placeholder,
|
||||
style,
|
||||
pageSize = 50,
|
||||
allowClear = true,
|
||||
disabled = false,
|
||||
}: PaginatedModelSelectProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [searchInput, setSearchInput] = useState("");
|
||||
const [debouncedSearch, setDebouncedSearch] = useDebouncedState("", {
|
||||
wait: DEBOUNCE_MS,
|
||||
|
|
@ -73,16 +75,16 @@ export const PaginatedModelSelect = ({
|
|||
{modelName ? (
|
||||
<Space direction="vertical">
|
||||
<Space direction="horizontal">
|
||||
<Text strong>Model name:</Text>
|
||||
<Text strong>{t("modelSelect.paginatedModelSelect.modelNameLabel")}</Text>
|
||||
<Text ellipsis>{modelName}</Text>
|
||||
</Space>
|
||||
<Text ellipsis type="secondary">
|
||||
Model ID: {modelId}
|
||||
{t("modelSelect.paginatedModelSelect.modelIdLabel")} {modelId}
|
||||
</Text>
|
||||
</Space>
|
||||
) : (
|
||||
<Text ellipsis type="secondary">
|
||||
Model ID: {modelId}
|
||||
{t("modelSelect.paginatedModelSelect.modelIdLabel")} {modelId}
|
||||
</Text>
|
||||
)}
|
||||
</>
|
||||
|
|
@ -112,7 +114,7 @@ export const PaginatedModelSelect = ({
|
|||
<Select
|
||||
value={value || undefined}
|
||||
onChange={handleChange}
|
||||
placeholder={placeholder}
|
||||
placeholder={placeholder ?? t("modelSelect.paginatedModelSelect.placeholder")}
|
||||
style={{ width: "100%", ...style }}
|
||||
allowClear={allowClear}
|
||||
disabled={disabled}
|
||||
|
|
@ -122,7 +124,7 @@ export const PaginatedModelSelect = ({
|
|||
searchValue={searchInput}
|
||||
onPopupScroll={handlePopupScroll}
|
||||
loading={isLoading}
|
||||
notFoundContent={isLoading ? <LoadingOutlined spin /> : "No models found"}
|
||||
notFoundContent={isLoading ? <LoadingOutlined spin /> : t("modelSelect.paginatedModelSelect.noModelsFound")}
|
||||
options={options}
|
||||
optionRender={optionRender}
|
||||
popupRender={(menu) => (
|
||||
|
|
|
|||
|
|
@ -8120,5 +8120,23 @@
|
|||
"deleteTitle": "Delete memory",
|
||||
"deleteMessage": "This action cannot be undone."
|
||||
}
|
||||
},
|
||||
"modelSelect": {
|
||||
"modelSelect": {
|
||||
"allProxyModels": "All Proxy Models",
|
||||
"noDefaultModels": "No Default Models",
|
||||
"specialOptions": "Special Options",
|
||||
"wildcardOptions": "Wildcard Options",
|
||||
"allProviderModels": "All {{provider}} models",
|
||||
"models": "Models",
|
||||
"selectModels": "Select Models",
|
||||
"moreModels": "+{{count}} more"
|
||||
},
|
||||
"paginatedModelSelect": {
|
||||
"placeholder": "Select a model",
|
||||
"modelNameLabel": "Model name:",
|
||||
"modelIdLabel": "Model ID:",
|
||||
"noModelsFound": "No models found"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8120,5 +8120,23 @@
|
|||
"deleteTitle": "删除记忆",
|
||||
"deleteMessage": "此操作不可撤销。"
|
||||
}
|
||||
},
|
||||
"modelSelect": {
|
||||
"modelSelect": {
|
||||
"allProxyModels": "所有代理模型",
|
||||
"noDefaultModels": "无默认模型",
|
||||
"specialOptions": "特殊选项",
|
||||
"wildcardOptions": "通配符选项",
|
||||
"allProviderModels": "所有 {{provider}} 模型",
|
||||
"models": "模型",
|
||||
"selectModels": "选择模型",
|
||||
"moreModels": "+{{count}} 个更多"
|
||||
},
|
||||
"paginatedModelSelect": {
|
||||
"placeholder": "选择模型",
|
||||
"modelNameLabel": "模型名称:",
|
||||
"modelIdLabel": "模型 ID:",
|
||||
"noModelsFound": "未找到模型"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue