feat: localize custom provider name and ollama placeholder (#75)
This commit is contained in:
committed by
GitHub
Unverified
parent
9844d3de95
commit
e8915831dc
@@ -328,7 +328,7 @@ function ProviderCard({
|
|||||||
<div className="relative flex-1">
|
<div className="relative flex-1">
|
||||||
<Input
|
<Input
|
||||||
type={showKey ? 'text' : 'password'}
|
type={showKey ? 'text' : 'password'}
|
||||||
placeholder={typeInfo?.requiresApiKey ? typeInfo?.placeholder : t('aiProviders.card.editKey')}
|
placeholder={typeInfo?.requiresApiKey ? typeInfo?.placeholder : (typeInfo?.id === 'ollama' ? t('aiProviders.notRequired') : t('aiProviders.card.editKey'))}
|
||||||
value={newKey}
|
value={newKey}
|
||||||
onChange={(e) => setNewKey(e.target.value)}
|
onChange={(e) => setNewKey(e.target.value)}
|
||||||
className="pr-10 h-9 text-sm"
|
className="pr-10 h-9 text-sm"
|
||||||
@@ -482,7 +482,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
|
|
||||||
await onAdd(
|
await onAdd(
|
||||||
selectedType,
|
selectedType,
|
||||||
name || typeInfo?.name || selectedType,
|
name || (typeInfo?.id === 'custom' ? t('aiProviders.custom') : typeInfo?.name) || selectedType,
|
||||||
apiKey.trim(),
|
apiKey.trim(),
|
||||||
{
|
{
|
||||||
baseUrl: baseUrl.trim() || undefined,
|
baseUrl: baseUrl.trim() || undefined,
|
||||||
@@ -513,7 +513,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
key={type.id}
|
key={type.id}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedType(type.id);
|
setSelectedType(type.id);
|
||||||
setName(type.name);
|
setName(type.id === 'custom' ? t('aiProviders.custom') : type.name);
|
||||||
setBaseUrl(type.defaultBaseUrl || '');
|
setBaseUrl(type.defaultBaseUrl || '');
|
||||||
setModelId(type.defaultModelId || '');
|
setModelId(type.defaultModelId || '');
|
||||||
}}
|
}}
|
||||||
@@ -524,7 +524,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
) : (
|
) : (
|
||||||
<span className="text-2xl">{type.icon}</span>
|
<span className="text-2xl">{type.icon}</span>
|
||||||
)}
|
)}
|
||||||
<p className="font-medium mt-2">{type.name}</p>
|
<p className="font-medium mt-2">{type.id === 'custom' ? t('aiProviders.custom') : type.name}</p>
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -537,7 +537,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
<span className="text-2xl">{typeInfo?.icon}</span>
|
<span className="text-2xl">{typeInfo?.icon}</span>
|
||||||
)}
|
)}
|
||||||
<div>
|
<div>
|
||||||
<p className="font-medium">{typeInfo?.name}</p>
|
<p className="font-medium">{typeInfo?.id === 'custom' ? t('aiProviders.custom') : typeInfo?.name}</p>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedType(null);
|
setSelectedType(null);
|
||||||
@@ -556,7 +556,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
<Label htmlFor="name">{t('aiProviders.dialog.displayName')}</Label>
|
<Label htmlFor="name">{t('aiProviders.dialog.displayName')}</Label>
|
||||||
<Input
|
<Input
|
||||||
id="name"
|
id="name"
|
||||||
placeholder={typeInfo?.name}
|
placeholder={typeInfo?.id === 'custom' ? t('aiProviders.custom') : typeInfo?.name}
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(e) => setName(e.target.value)}
|
onChange={(e) => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
@@ -568,7 +568,7 @@ function AddProviderDialog({ existingTypes, onClose, onAdd, onValidateKey }: Add
|
|||||||
<Input
|
<Input
|
||||||
id="apiKey"
|
id="apiKey"
|
||||||
type={showKey ? 'text' : 'password'}
|
type={showKey ? 'text' : 'password'}
|
||||||
placeholder={typeInfo?.placeholder}
|
placeholder={typeInfo?.id === 'ollama' ? t('aiProviders.notRequired') : typeInfo?.placeholder}
|
||||||
value={apiKey}
|
value={apiKey}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setApiKey(e.target.value);
|
setApiKey(e.target.value);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"title": "AI Providers",
|
"title": "AI Providers",
|
||||||
"description": "Configure your AI model providers and API keys",
|
"description": "Configure your AI model providers and API keys",
|
||||||
"add": "Add Provider",
|
"add": "Add Provider",
|
||||||
|
"custom": "Custom",
|
||||||
|
"notRequired": "Not required",
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "No providers configured",
|
"title": "No providers configured",
|
||||||
"desc": "Add an AI provider to start using ClawX",
|
"desc": "Add an AI provider to start using ClawX",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"title": "AI プロバイダー",
|
"title": "AI プロバイダー",
|
||||||
"description": "AI モデルプロバイダーと API キーを設定",
|
"description": "AI モデルプロバイダーと API キーを設定",
|
||||||
"add": "プロバイダーを追加",
|
"add": "プロバイダーを追加",
|
||||||
|
"custom": "カスタム",
|
||||||
|
"notRequired": "不要",
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "プロバイダーが構成されていません",
|
"title": "プロバイダーが構成されていません",
|
||||||
"desc": "ClawX の使用を開始するには AI プロバイダーを追加してください",
|
"desc": "ClawX の使用を開始するには AI プロバイダーを追加してください",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"title": "AI 模型提供商",
|
"title": "AI 模型提供商",
|
||||||
"description": "配置 AI 模型提供商和 API 密钥",
|
"description": "配置 AI 模型提供商和 API 密钥",
|
||||||
"add": "添加提供商",
|
"add": "添加提供商",
|
||||||
|
"custom": "自定义",
|
||||||
|
"notRequired": "非必填",
|
||||||
"empty": {
|
"empty": {
|
||||||
"title": "未配置提供商",
|
"title": "未配置提供商",
|
||||||
"desc": "添加 AI 提供商以开始使用 ClawX",
|
"desc": "添加 AI 提供商以开始使用 ClawX",
|
||||||
|
|||||||
@@ -682,7 +682,7 @@ function ProviderContent({
|
|||||||
onApiKeyChange,
|
onApiKeyChange,
|
||||||
onConfiguredChange,
|
onConfiguredChange,
|
||||||
}: ProviderContentProps) {
|
}: ProviderContentProps) {
|
||||||
const { t } = useTranslation('setup');
|
const { t } = useTranslation(['setup', 'settings']);
|
||||||
const [showKey, setShowKey] = useState(false);
|
const [showKey, setShowKey] = useState(false);
|
||||||
const [validating, setValidating] = useState(false);
|
const [validating, setValidating] = useState(false);
|
||||||
const [keyValid, setKeyValid] = useState<boolean | null>(null);
|
const [keyValid, setKeyValid] = useState<boolean | null>(null);
|
||||||
@@ -841,7 +841,7 @@ function ProviderContent({
|
|||||||
'provider:save',
|
'provider:save',
|
||||||
{
|
{
|
||||||
id: providerIdForSave,
|
id: providerIdForSave,
|
||||||
name: selectedProviderData?.name || selectedProvider,
|
name: selectedProvider === 'custom' ? t('settings:aiProviders.custom') : (selectedProviderData?.name || selectedProvider),
|
||||||
type: selectedProvider,
|
type: selectedProvider,
|
||||||
baseUrl: baseUrl.trim() || undefined,
|
baseUrl: baseUrl.trim() || undefined,
|
||||||
model: effectiveModelId,
|
model: effectiveModelId,
|
||||||
@@ -925,7 +925,7 @@ function ProviderContent({
|
|||||||
)}
|
)}
|
||||||
<span className={cn('truncate text-left', !selectedProvider && 'text-muted-foreground')}>
|
<span className={cn('truncate text-left', !selectedProvider && 'text-muted-foreground')}>
|
||||||
{selectedProviderData
|
{selectedProviderData
|
||||||
? `${selectedProviderData.name}${selectedProviderData.model ? ` — ${selectedProviderData.model}` : ''}`
|
? `${selectedProviderData.id === 'custom' ? t('settings:aiProviders.custom') : selectedProviderData.name}${selectedProviderData.model ? ` — ${selectedProviderData.model}` : ''}`
|
||||||
: t('provider.selectPlaceholder')}
|
: t('provider.selectPlaceholder')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -964,7 +964,7 @@ function ProviderContent({
|
|||||||
) : (
|
) : (
|
||||||
<span className="text-sm leading-none shrink-0">{p.icon}</span>
|
<span className="text-sm leading-none shrink-0">{p.icon}</span>
|
||||||
)}
|
)}
|
||||||
<span className="truncate">{p.name}{p.model ? ` — ${p.model}` : ''}</span>
|
<span className="truncate">{p.id === 'custom' ? t('settings:aiProviders.custom') : p.name}{p.model ? ` — ${p.model}` : ''}</span>
|
||||||
</div>
|
</div>
|
||||||
{isSelected && <Check className="h-4 w-4 text-primary shrink-0" />}
|
{isSelected && <Check className="h-4 w-4 text-primary shrink-0" />}
|
||||||
</button>
|
</button>
|
||||||
@@ -1527,7 +1527,7 @@ interface CompleteContentProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CompleteContent({ selectedProvider, installedSkills }: CompleteContentProps) {
|
function CompleteContent({ selectedProvider, installedSkills }: CompleteContentProps) {
|
||||||
const { t } = useTranslation('setup');
|
const { t } = useTranslation(['setup', 'settings']);
|
||||||
const gatewayStatus = useGatewayStore((state) => state.status);
|
const gatewayStatus = useGatewayStore((state) => state.status);
|
||||||
|
|
||||||
const providerData = providers.find((p) => p.id === selectedProvider);
|
const providerData = providers.find((p) => p.id === selectedProvider);
|
||||||
@@ -1548,7 +1548,7 @@ function CompleteContent({ selectedProvider, installedSkills }: CompleteContentP
|
|||||||
<div className="flex items-center justify-between p-3 rounded-lg bg-muted/50">
|
<div className="flex items-center justify-between p-3 rounded-lg bg-muted/50">
|
||||||
<span>{t('complete.provider')}</span>
|
<span>{t('complete.provider')}</span>
|
||||||
<span className="text-green-400">
|
<span className="text-green-400">
|
||||||
{providerData ? <span className="flex items-center gap-1.5">{getProviderIconUrl(providerData.id) ? <img src={getProviderIconUrl(providerData.id)} alt={providerData.name} className={`h-4 w-4 inline-block ${shouldInvertInDark(providerData.id) ? 'dark:invert' : ''}`} /> : providerData.icon} {providerData.name}</span> : '—'}
|
{providerData ? <span className="flex items-center gap-1.5">{getProviderIconUrl(providerData.id) ? <img src={getProviderIconUrl(providerData.id)} alt={providerData.name} className={`h-4 w-4 inline-block ${shouldInvertInDark(providerData.id) ? 'dark:invert' : ''}`} /> : providerData.icon} {providerData.id === 'custom' ? t('settings:aiProviders.custom') : providerData.name}</span> : '—'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between p-3 rounded-lg bg-muted/50">
|
<div className="flex items-center justify-between p-3 rounded-lg bg-muted/50">
|
||||||
|
|||||||
Reference in New Issue
Block a user