feat(ui): i18n for model select components

This commit is contained in:
吹雪 2026-06-11 06:46:57 +09:00
parent 3cbbffbac4
commit 950a51ff9c
4 changed files with 59 additions and 17 deletions

View file

@ -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>
)}
/>

View file

@ -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) => (

View file

@ -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"
}
}
}

View file

@ -8120,5 +8120,23 @@
"deleteTitle": "删除记忆",
"deleteMessage": "此操作不可撤销。"
}
},
"modelSelect": {
"modelSelect": {
"allProxyModels": "所有代理模型",
"noDefaultModels": "无默认模型",
"specialOptions": "特殊选项",
"wildcardOptions": "通配符选项",
"allProviderModels": "所有 {{provider}} 模型",
"models": "模型",
"selectModels": "选择模型",
"moreModels": "+{{count}} 个更多"
},
"paginatedModelSelect": {
"placeholder": "选择模型",
"modelNameLabel": "模型名称:",
"modelIdLabel": "模型 ID:",
"noModelsFound": "未找到模型"
}
}
}