refactor: enhance model trigger component with internationalization support and improved tooltip handling

This commit is contained in:
CodingOnStar
2026-03-06 14:50:23 +08:00
parent e371bfd676
commit ff4e4a8d64
4 changed files with 51 additions and 28 deletions

View File

@ -3,18 +3,23 @@ import type {
Model,
ModelItem,
} from '../declarations'
import { RiArrowDownSLine } from '@remixicon/react'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/line/alertsAndFeedback'
import Tooltip from '@/app/components/base/tooltip'
import { useTranslation } from 'react-i18next'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/app/components/base/ui/tooltip'
import { cn } from '@/utils/classnames'
import {
MODEL_STATUS_TEXT,
ModelStatusEnum,
} from '../declarations'
import { useLanguage } from '../hooks'
import ModelIcon from '../model-icon'
import ModelName from '../model-name'
const STATUS_I18N_KEY: Partial<Record<ModelStatusEnum, string>> = {
[ModelStatusEnum.quotaExceeded]: 'modelProvider.selector.creditsExhausted',
[ModelStatusEnum.noConfigure]: 'modelProvider.selector.configureRequired',
[ModelStatusEnum.noPermission]: 'modelProvider.selector.incompatible',
[ModelStatusEnum.disabled]: 'modelProvider.selector.disabled',
[ModelStatusEnum.credentialRemoved]: 'modelProvider.selector.apiKeyUnavailable',
}
type ModelTriggerProps = {
open: boolean
provider: Model
@ -29,7 +34,9 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
className,
readonly,
}) => {
const language = useLanguage()
const { t } = useTranslation()
const isActive = model.status === ModelStatusEnum.active
const statusI18nKey = STATUS_I18N_KEY[model.status]
return (
<div
@ -37,7 +44,7 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
'group flex h-8 items-center gap-0.5 rounded-lg bg-components-input-bg-normal p-1',
!readonly && 'cursor-pointer hover:bg-components-input-bg-hover',
open && 'bg-components-input-bg-hover',
model.status !== ModelStatusEnum.active && 'bg-components-input-bg-disabled hover:bg-components-input-bg-disabled',
!isActive && 'bg-components-input-bg-disabled hover:bg-components-input-bg-disabled',
className,
)}
>
@ -53,22 +60,26 @@ const ModelTrigger: FC<ModelTriggerProps> = ({
showMode
showFeatures
/>
{!readonly && (
<div className="flex h-4 w-4 shrink-0 items-center justify-center">
{
model.status !== ModelStatusEnum.active
? (
<Tooltip popupContent={MODEL_STATUS_TEXT[model.status][language]}>
<AlertTriangle className="h-4 w-4 text-text-warning-secondary" />
</Tooltip>
)
: (
<RiArrowDownSLine
className="h-3.5 w-3.5 text-text-tertiary"
/>
)
}
</div>
{!readonly && !isActive && statusI18nKey && (
<Tooltip>
<TooltipTrigger
disabled={model.status !== ModelStatusEnum.noPermission}
render={(
<div className="flex shrink-0 items-center gap-[3px] rounded-md border border-text-warning px-[5px] py-0.5">
<span className="i-ri-alert-fill h-3 w-3 text-text-warning" />
<span className="whitespace-nowrap text-text-warning system-xs-medium">
{t(statusI18nKey as 'modelProvider.selector.creditsExhausted', { ns: 'common' })}
</span>
</div>
)}
/>
<TooltipContent placement="top" className="z-[1003]">
{t('modelProvider.selector.incompatibleTip', { ns: 'common' })}
</TooltipContent>
</Tooltip>
)}
{!readonly && isActive && (
<span className="i-ri-arrow-down-s-line h-3.5 w-3.5 shrink-0 text-text-tertiary" />
)}
</div>
</div>

View File

@ -4891,11 +4891,6 @@
"count": 1
}
},
"app/components/header/account-setting/model-provider-page/model-selector/model-trigger.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx": {
"no-restricted-imports": {
"count": 1

View File

@ -404,13 +404,17 @@
"modelProvider.searchModel": "Search model",
"modelProvider.selectModel": "Select your model",
"modelProvider.selector.aiCredits": "AI credits",
"modelProvider.selector.apiKeyUnavailable": "API Key unavailable",
"modelProvider.selector.configure": "Configure",
"modelProvider.selector.configureRequired": "Configure required",
"modelProvider.selector.creditsExhausted": "Credits exhausted",
"modelProvider.selector.disabled": "Disabled",
"modelProvider.selector.discoverMoreInMarketplace": "Discover more in Marketplace",
"modelProvider.selector.emptySetting": "Please go to settings to configure",
"modelProvider.selector.emptyTip": "No available models",
"modelProvider.selector.fromMarketplace": "From Marketplace",
"modelProvider.selector.incompatible": "Incompatible",
"modelProvider.selector.incompatibleTip": "This model is not available in the current version. Please select another available model.",
"modelProvider.selector.install": "Install",
"modelProvider.selector.noProviderConfigured": "No model provider configured",
"modelProvider.selector.noProviderConfiguredDesc": "Browse Marketplace to install one, or configure providers in settings.",

View File

@ -403,8 +403,21 @@
"modelProvider.resetDate": "于 {{date}} 重置",
"modelProvider.searchModel": "搜索模型",
"modelProvider.selectModel": "选择您的模型",
"modelProvider.selector.aiCredits": "AI 积分",
"modelProvider.selector.apiKeyUnavailable": "API Key 不可用",
"modelProvider.selector.configure": "配置",
"modelProvider.selector.configureRequired": "需要配置",
"modelProvider.selector.creditsExhausted": "额度已用尽",
"modelProvider.selector.disabled": "已禁用",
"modelProvider.selector.discoverMoreInMarketplace": "在插件市场发现更多",
"modelProvider.selector.emptySetting": "请前往设置进行配置",
"modelProvider.selector.emptyTip": "无可用模型",
"modelProvider.selector.fromMarketplace": "从插件市场安装",
"modelProvider.selector.incompatible": "不兼容",
"modelProvider.selector.incompatibleTip": "该模型在当前版本中不可用,请选择其他可用模型。",
"modelProvider.selector.install": "安装",
"modelProvider.selector.noProviderConfigured": "未配置模型提供商",
"modelProvider.selector.noProviderConfiguredDesc": "前往插件市场安装,或在设置中配置提供商。",
"modelProvider.selector.rerankTip": "请设置 Rerank 模型",
"modelProvider.selector.tip": "该模型已被删除。请添模型或选择其他模型。",
"modelProvider.setupModelFirst": "请先设置您的模型",