From 6415a0b79971a3fd149f0ae353bdc0092ab2356e Mon Sep 17 00:00:00 2001 From: yyh Date: Fri, 13 Feb 2026 19:04:51 +0800 Subject: [PATCH] refactor(web): remove sandbox provider literals from i18n --- .../sandbox-provider-page/config-modal.tsx | 10 ++-- .../sandbox-provider-page/constants.ts | 49 +++++++++++++------ .../sandbox-provider-page/provider-card.tsx | 6 ++- .../sandbox-provider-page/switch-modal.tsx | 6 ++- web/i18n/en-US/common.json | 12 ----- web/i18n/ja-JP/common.json | 12 ----- web/i18n/zh-Hans/common.json | 12 ----- 7 files changed, 49 insertions(+), 58 deletions(-) diff --git a/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx b/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx index 27792df327..552891eb26 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx +++ b/web/app/components/header/account-setting/sandbox-provider-page/config-modal.tsx @@ -17,7 +17,7 @@ import { useSaveSandboxProviderConfig, } from '@/service/use-sandbox-provider' import { cn } from '@/utils/classnames' -import { PROVIDER_DOC_LINKS, PROVIDER_LABEL_KEYS, SANDBOX_FIELD_CONFIGS } from './constants' +import { PROVIDER_DOC_LINKS, PROVIDER_STATIC_LABELS, SANDBOX_FIELD_CONFIGS } from './constants' import ProviderIcon from './provider-icon' type ConfigMode = 'managed' | 'byok' @@ -95,7 +95,9 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { return { name: schema.name, label: fieldConfig ? t(fieldConfig.labelKey, { ns: 'common' }) : schema.name, - placeholder: fieldConfig ? t(fieldConfig.placeholderKey, { ns: 'common' }) : '', + placeholder: fieldConfig + ? (fieldConfig.placeholder ?? (fieldConfig.placeholderKey ? t(fieldConfig.placeholderKey, { ns: 'common' }) : '')) + : '', type: fieldConfig?.type ?? fallbackType, required: schema.name === 'api_key', default: provider.config[schema.name] || '', @@ -151,8 +153,8 @@ function ConfigModal({ provider, onClose }: ConfigModalProps) { }, [deleteConfig, provider.provider_type, notify, t, onClose]) const docLink = PROVIDER_DOC_LINKS[provider.provider_type] - const providerLabelKey = PROVIDER_LABEL_KEYS[provider.provider_type as keyof typeof PROVIDER_LABEL_KEYS] ?? 'sandboxProvider.e2b.label' - const providerLabel = t(providerLabelKey, { ns: 'common' }) + const providerLabel = PROVIDER_STATIC_LABELS[provider.provider_type as keyof typeof PROVIDER_STATIC_LABELS] + ?? provider.provider_type // Only show revoke button when in BYOK mode, tenant has custom config, and provider is not active // (active provider cannot be revoked to prevent "no sandbox provider" error) diff --git a/web/app/components/header/account-setting/sandbox-provider-page/constants.ts b/web/app/components/header/account-setting/sandbox-provider-page/constants.ts index 4fa4531af1..7c02b00307 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/constants.ts +++ b/web/app/components/header/account-setting/sandbox-provider-page/constants.ts @@ -8,12 +8,12 @@ export const PROVIDER_ICONS: Record = { ssh: '/sandbox-providers/ssh.svg', } -export const PROVIDER_LABEL_KEYS = { - e2b: 'sandboxProvider.e2b.label', - daytona: 'sandboxProvider.daytona.label', - docker: 'sandboxProvider.docker.label', - local: 'sandboxProvider.local.label', - ssh: 'sandboxProvider.ssh.label', +export const PROVIDER_STATIC_LABELS = { + e2b: 'E2B', + daytona: 'Daytona', + docker: 'Docker', + local: 'Local', + ssh: 'SSH', } as const export const PROVIDER_DESCRIPTION_KEYS = { @@ -24,7 +24,28 @@ export const PROVIDER_DESCRIPTION_KEYS = { ssh: 'sandboxProvider.ssh.description', } as const -export const SANDBOX_FIELD_CONFIGS = { +type SandboxFieldConfig = { + labelKey: + | 'sandboxProvider.configModal.apiKey' + | 'sandboxProvider.configModal.e2bApiUrl' + | 'sandboxProvider.configModal.e2bTemplate' + | 'sandboxProvider.configModal.dockerSock' + | 'sandboxProvider.configModal.dockerImage' + | 'sandboxProvider.configModal.baseWorkingPath' + | 'sandboxProvider.configModal.sshHost' + | 'sandboxProvider.configModal.sshPort' + | 'sandboxProvider.configModal.sshUsername' + | 'sandboxProvider.configModal.sshPassword' + placeholderKey?: + | 'sandboxProvider.configModal.apiKeyPlaceholder' + | 'sandboxProvider.configModal.e2bTemplatePlaceholder' + | 'sandboxProvider.configModal.sshUsernamePlaceholder' + | 'sandboxProvider.configModal.sshPasswordPlaceholder' + placeholder?: string + type: FormTypeEnum +} + +export const SANDBOX_FIELD_CONFIGS: Record = { api_key: { labelKey: 'sandboxProvider.configModal.apiKey', placeholderKey: 'sandboxProvider.configModal.apiKeyPlaceholder', @@ -32,7 +53,7 @@ export const SANDBOX_FIELD_CONFIGS = { }, e2b_api_url: { labelKey: 'sandboxProvider.configModal.e2bApiUrl', - placeholderKey: 'sandboxProvider.configModal.e2bApiUrlPlaceholder', + placeholder: 'https://api.e2b.app', type: FormTypeEnum.textInput, }, e2b_default_template: { @@ -42,27 +63,27 @@ export const SANDBOX_FIELD_CONFIGS = { }, docker_sock: { labelKey: 'sandboxProvider.configModal.dockerSock', - placeholderKey: 'sandboxProvider.configModal.dockerSockPlaceholder', + placeholder: 'unix:///var/run/docker.sock', type: FormTypeEnum.textInput, }, docker_image: { labelKey: 'sandboxProvider.configModal.dockerImage', - placeholderKey: 'sandboxProvider.configModal.dockerImagePlaceholder', + placeholder: 'ubuntu:latest', type: FormTypeEnum.textInput, }, base_working_path: { labelKey: 'sandboxProvider.configModal.baseWorkingPath', - placeholderKey: 'sandboxProvider.configModal.baseWorkingPathPlaceholder', + placeholder: '/workspace/sandboxes', type: FormTypeEnum.textInput, }, ssh_host: { labelKey: 'sandboxProvider.configModal.sshHost', - placeholderKey: 'sandboxProvider.configModal.sshHostPlaceholder', + placeholder: 'e.g. 127.0.0.1 or agentbox', type: FormTypeEnum.textInput, }, ssh_port: { labelKey: 'sandboxProvider.configModal.sshPort', - placeholderKey: 'sandboxProvider.configModal.sshPortPlaceholder', + placeholder: '22', type: FormTypeEnum.textInput, }, ssh_username: { @@ -75,7 +96,7 @@ export const SANDBOX_FIELD_CONFIGS = { placeholderKey: 'sandboxProvider.configModal.sshPasswordPlaceholder', type: FormTypeEnum.secretInput, }, -} as const +} export const PROVIDER_DOC_LINKS: Record = { e2b: 'https://e2b.dev/docs', diff --git a/web/app/components/header/account-setting/sandbox-provider-page/provider-card.tsx b/web/app/components/header/account-setting/sandbox-provider-page/provider-card.tsx index 493620f1ff..a42eae6f4a 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/provider-card.tsx +++ b/web/app/components/header/account-setting/sandbox-provider-page/provider-card.tsx @@ -8,7 +8,7 @@ import Button from '@/app/components/base/button' import Indicator from '@/app/components/header/indicator' import { IS_CLOUD_EDITION } from '@/config' import { cn } from '@/utils/classnames' -import { PROVIDER_DESCRIPTION_KEYS, PROVIDER_LABEL_KEYS } from './constants' +import { PROVIDER_DESCRIPTION_KEYS, PROVIDER_STATIC_LABELS } from './constants' import ProviderIcon from './provider-icon' type ProviderCardProps = { @@ -30,6 +30,8 @@ const ProviderCard = ({ const isConfigured = provider.is_tenant_configured || provider.is_system_configured const showEnableButton = !disabled && !isCurrent && isConfigured && onEnable + const providerLabel = PROVIDER_STATIC_LABELS[provider.provider_type as keyof typeof PROVIDER_STATIC_LABELS] + ?? provider.provider_type return (
- {t(PROVIDER_LABEL_KEYS[provider.provider_type as keyof typeof PROVIDER_LABEL_KEYS] ?? 'sandboxProvider.e2b.label', { ns: 'common' })} + {providerLabel} {IS_CLOUD_EDITION && provider.is_system_configured && !provider.is_tenant_configured && ( diff --git a/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx b/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx index 0f5eaf086c..70025fe979 100644 --- a/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx +++ b/web/app/components/header/account-setting/sandbox-provider-page/switch-modal.tsx @@ -7,7 +7,7 @@ import Button from '@/app/components/base/button' import Modal from '@/app/components/base/modal' import { useToastContext } from '@/app/components/base/toast' import { useActivateSandboxProvider } from '@/service/use-sandbox-provider' -import { PROVIDER_LABEL_KEYS } from './constants' +import { PROVIDER_STATIC_LABELS } from './constants' type SwitchModalProps = { provider: SandboxProvider @@ -22,6 +22,8 @@ const SwitchModal = ({ const { notify } = useToastContext() const { mutateAsync: activateProvider, isPending } = useActivateSandboxProvider() + const providerLabel = PROVIDER_STATIC_LABELS[provider.provider_type as keyof typeof PROVIDER_STATIC_LABELS] + ?? provider.provider_type // Determine the type based on provider configuration // If tenant has custom config, activate as 'user', otherwise as 'system' @@ -62,7 +64,7 @@ const SwitchModal = ({ }} />
diff --git a/web/i18n/en-US/common.json b/web/i18n/en-US/common.json index 25e0f2866f..b34b5fdcf2 100644 --- a/web/i18n/en-US/common.json +++ b/web/i18n/en-US/common.json @@ -565,22 +565,17 @@ "provider.validating": "Validating key...", "sandboxProvider.config": "Config", "sandboxProvider.configModal.apiEndpoint": "API Endpoint", - "sandboxProvider.configModal.apiEndpointPlaceholder": "https://api.example.com/v1", "sandboxProvider.configModal.apiKey": "API Key / Secret", "sandboxProvider.configModal.apiKeyPlaceholder": "Enter your API key", "sandboxProvider.configModal.baseWorkingPath": "Base Working Path", - "sandboxProvider.configModal.baseWorkingPathPlaceholder": "/workspace/sandboxes", "sandboxProvider.configModal.bringYourOwnKey": "Bring Your Own E2B API Key", "sandboxProvider.configModal.bringYourOwnKeyDesc": "Connect using your own E2B account. No usage limits from Dify, with full control over resources and billing.", "sandboxProvider.configModal.cancel": "Cancel", "sandboxProvider.configModal.confirm": "Confirm", "sandboxProvider.configModal.connectionMode": "Connect Mode", "sandboxProvider.configModal.dockerImage": "Docker Image", - "sandboxProvider.configModal.dockerImagePlaceholder": "ubuntu:latest", "sandboxProvider.configModal.dockerSock": "Docker Socket", - "sandboxProvider.configModal.dockerSockPlaceholder": "unix:///var/run/docker.sock", "sandboxProvider.configModal.e2bApiUrl": "E2B API URL", - "sandboxProvider.configModal.e2bApiUrlPlaceholder": "https://api.e2b.app", "sandboxProvider.configModal.e2bTemplate": "E2B Template", "sandboxProvider.configModal.e2bTemplatePlaceholder": "code-interpreter-v1", "sandboxProvider.configModal.managedByDify": "Managed by Dify", @@ -592,32 +587,25 @@ "sandboxProvider.configModal.securityTip": "Your API Token will be encrypted and stored using", "sandboxProvider.configModal.securityTipTechnology": "technology.", "sandboxProvider.configModal.sshHost": "SSH Host", - "sandboxProvider.configModal.sshHostPlaceholder": "e.g. 127.0.0.1 or agentbox", "sandboxProvider.configModal.sshPassword": "SSH Password", "sandboxProvider.configModal.sshPasswordPlaceholder": "Enter SSH password", "sandboxProvider.configModal.sshPort": "SSH Port", - "sandboxProvider.configModal.sshPortPlaceholder": "22", "sandboxProvider.configModal.sshUsername": "SSH Username", "sandboxProvider.configModal.sshUsernamePlaceholder": "agentbox", "sandboxProvider.configModal.title": "Configure Sandbox Provider", "sandboxProvider.connected": "CONNECTED", "sandboxProvider.currentProvider": "CURRENT ACTIVE", "sandboxProvider.daytona.description": "Deploy AI code with confidence using Daytona's lightning-fast infrastructure.", - "sandboxProvider.daytona.label": "Daytona", "sandboxProvider.docker.description": "The Easiest Way to Build, Run, and Secure Agents.", - "sandboxProvider.docker.label": "Docker", "sandboxProvider.e2b.description": "E2B Gives AI Agents Secure Computers with Real-World Tools.", - "sandboxProvider.e2b.label": "E2B", "sandboxProvider.enable": "Enable", "sandboxProvider.local.description": "This mode will provide the host machine as an agent, and its use in production is not recommended.", - "sandboxProvider.local.label": "Local", "sandboxProvider.managedBySaas": "Managed by SaaS", "sandboxProvider.noPermission": "Contact the workspace administrator to make changes.", "sandboxProvider.notConfigured": "Not Configured", "sandboxProvider.otherProvider": "OTHER PROVIDERS", "sandboxProvider.setAsActive": "Set as Active", "sandboxProvider.ssh.description": "Run agent workloads in a remote SSH with file transfer support.", - "sandboxProvider.ssh.label": "SSH", "sandboxProvider.switchModal.cancel": "Cancel", "sandboxProvider.switchModal.confirm": "Switch", "sandboxProvider.switchModal.confirmText": "You are about to switch the active sandbox provider to {{provider}}.", diff --git a/web/i18n/ja-JP/common.json b/web/i18n/ja-JP/common.json index 2c7cca267a..e588cc387d 100644 --- a/web/i18n/ja-JP/common.json +++ b/web/i18n/ja-JP/common.json @@ -565,22 +565,17 @@ "provider.validating": "キーの検証中...", "sandboxProvider.config": "設定", "sandboxProvider.configModal.apiEndpoint": "API エンドポイント", - "sandboxProvider.configModal.apiEndpointPlaceholder": "https://api.example.com/v1", "sandboxProvider.configModal.apiKey": "API キー / シークレット", "sandboxProvider.configModal.apiKeyPlaceholder": "API キーを入力してください", "sandboxProvider.configModal.baseWorkingPath": "ベースワーキングパス", - "sandboxProvider.configModal.baseWorkingPathPlaceholder": "/workspace/sandboxes", "sandboxProvider.configModal.bringYourOwnKey": "独自の E2B API キーを利用", "sandboxProvider.configModal.bringYourOwnKeyDesc": "自身の E2B アカウントで接続します。Dify 側の利用制限はなく、リソースと課金を完全に管理できます。", "sandboxProvider.configModal.cancel": "キャンセル", "sandboxProvider.configModal.confirm": "確認", "sandboxProvider.configModal.connectionMode": "接続モード", "sandboxProvider.configModal.dockerImage": "Docker イメージ", - "sandboxProvider.configModal.dockerImagePlaceholder": "ubuntu:latest", "sandboxProvider.configModal.dockerSock": "Docker ソケット", - "sandboxProvider.configModal.dockerSockPlaceholder": "unix:///var/run/docker.sock", "sandboxProvider.configModal.e2bApiUrl": "E2B API URL", - "sandboxProvider.configModal.e2bApiUrlPlaceholder": "https://api.e2b.app", "sandboxProvider.configModal.e2bTemplate": "E2B テンプレート", "sandboxProvider.configModal.e2bTemplatePlaceholder": "code-interpreter-v1", "sandboxProvider.configModal.managedByDify": "Dify により管理", @@ -592,32 +587,25 @@ "sandboxProvider.configModal.securityTip": "API トークンは ", "sandboxProvider.configModal.securityTipTechnology": " によって暗号化・保存されます。", "sandboxProvider.configModal.sshHost": "SSH ホスト", - "sandboxProvider.configModal.sshHostPlaceholder": "例: 127.0.0.1 または agentbox", "sandboxProvider.configModal.sshPassword": "SSH パスワード", "sandboxProvider.configModal.sshPasswordPlaceholder": "SSH パスワードを入力してください", "sandboxProvider.configModal.sshPort": "SSH ポート", - "sandboxProvider.configModal.sshPortPlaceholder": "22", "sandboxProvider.configModal.sshUsername": "SSH ユーザー名", "sandboxProvider.configModal.sshUsernamePlaceholder": "agentbox", "sandboxProvider.configModal.title": "サンドボックスプロバイダーを設定", "sandboxProvider.connected": "接続済み", "sandboxProvider.currentProvider": "現在アクティブ", "sandboxProvider.daytona.description": "Daytona の超高速インフラストラクチャを使用して、自信を持って AI コードをデプロイします。", - "sandboxProvider.daytona.label": "Daytona", "sandboxProvider.docker.description": "エージェントを構築、実行、保護する最も簡単な方法。", - "sandboxProvider.docker.label": "Docker", "sandboxProvider.e2b.description": "E2B は、AI エージェントに現実世界のツールを備えた安全なコンピューターを提供します。", - "sandboxProvider.e2b.label": "E2B", "sandboxProvider.enable": "有効にする", "sandboxProvider.local.description": "このモードではホストマシンをエージェントとして使用します。本番環境での利用は推奨されません。", - "sandboxProvider.local.label": "ローカル", "sandboxProvider.managedBySaas": "SaaS により管理", "sandboxProvider.noPermission": "変更するにはワークスペース管理者に連絡してください。", "sandboxProvider.notConfigured": "未構成", "sandboxProvider.otherProvider": "その他のプロバイダー", "sandboxProvider.setAsActive": "アクティブに設定", "sandboxProvider.ssh.description": "ファイル転送サポートを使用して、リモート SSH でエージェント ワークロードを実行します。", - "sandboxProvider.ssh.label": "SSH", "sandboxProvider.switchModal.cancel": "キャンセル", "sandboxProvider.switchModal.confirm": "切り替え", "sandboxProvider.switchModal.confirmText": "アクティブなサンドボックスプロバイダーを {{provider}} に切り替えようとしています。", diff --git a/web/i18n/zh-Hans/common.json b/web/i18n/zh-Hans/common.json index 79604bd4db..892a81518c 100644 --- a/web/i18n/zh-Hans/common.json +++ b/web/i18n/zh-Hans/common.json @@ -565,22 +565,17 @@ "provider.validating": "验证密钥中...", "sandboxProvider.config": "配置", "sandboxProvider.configModal.apiEndpoint": "API 端点", - "sandboxProvider.configModal.apiEndpointPlaceholder": "https://api.example.com/v1", "sandboxProvider.configModal.apiKey": "API Key / 密钥", "sandboxProvider.configModal.apiKeyPlaceholder": "输入您的 API Key", "sandboxProvider.configModal.baseWorkingPath": "基础工作路径", - "sandboxProvider.configModal.baseWorkingPathPlaceholder": "/workspace/sandboxes", "sandboxProvider.configModal.bringYourOwnKey": "使用自己的 E2B API Key", "sandboxProvider.configModal.bringYourOwnKeyDesc": "使用您自己的 E2B 账户连接。无 Dify 使用限制,完全控制资源和计费。", "sandboxProvider.configModal.cancel": "取消", "sandboxProvider.configModal.confirm": "确认", "sandboxProvider.configModal.connectionMode": "连接模式", "sandboxProvider.configModal.dockerImage": "Docker 镜像", - "sandboxProvider.configModal.dockerImagePlaceholder": "ubuntu:latest", "sandboxProvider.configModal.dockerSock": "Docker Socket", - "sandboxProvider.configModal.dockerSockPlaceholder": "unix:///var/run/docker.sock", "sandboxProvider.configModal.e2bApiUrl": "E2B API 地址", - "sandboxProvider.configModal.e2bApiUrlPlaceholder": "https://api.e2b.app", "sandboxProvider.configModal.e2bTemplate": "E2B 模板", "sandboxProvider.configModal.e2bTemplatePlaceholder": "code-interpreter-v1", "sandboxProvider.configModal.managedByDify": "由 Dify 托管", @@ -592,32 +587,25 @@ "sandboxProvider.configModal.securityTip": "您的 API Token 将使用", "sandboxProvider.configModal.securityTipTechnology": "技术加密存储。", "sandboxProvider.configModal.sshHost": "SSH 主机", - "sandboxProvider.configModal.sshHostPlaceholder": "例如 127.0.0.1 或 agentbox", "sandboxProvider.configModal.sshPassword": "SSH 密码", "sandboxProvider.configModal.sshPasswordPlaceholder": "请输入 SSH 密码", "sandboxProvider.configModal.sshPort": "SSH 端口", - "sandboxProvider.configModal.sshPortPlaceholder": "22", "sandboxProvider.configModal.sshUsername": "SSH 用户名", "sandboxProvider.configModal.sshUsernamePlaceholder": "agentbox", "sandboxProvider.configModal.title": "配置 Sandbox Provider", "sandboxProvider.connected": "已连接", "sandboxProvider.currentProvider": "当前激活", "sandboxProvider.daytona.description": "使用 Daytona 的高性能基础设施,自信地部署 AI 代码。", - "sandboxProvider.daytona.label": "Daytona", "sandboxProvider.docker.description": "构建、运行和保护代理的最简单方式。", - "sandboxProvider.docker.label": "Docker", "sandboxProvider.e2b.description": "E2B 为 AI 代理提供真实世界工具的安全计算环境。", - "sandboxProvider.e2b.label": "E2B", "sandboxProvider.enable": "启用", "sandboxProvider.local.description": "此模式将主机作为代理提供,不建议在生产环境中使用。", - "sandboxProvider.local.label": "本地", "sandboxProvider.managedBySaas": "由 SaaS 管理", "sandboxProvider.noPermission": "请联系工作空间管理员进行更改。", "sandboxProvider.notConfigured": "未配置", "sandboxProvider.otherProvider": "其他供应商", "sandboxProvider.setAsActive": "设为激活", "sandboxProvider.ssh.description": "通过 SSH 连接远程虚拟机运行代理任务,并支持文件传输。", - "sandboxProvider.ssh.label": "SSH 虚拟机", "sandboxProvider.switchModal.cancel": "取消", "sandboxProvider.switchModal.confirm": "切换", "sandboxProvider.switchModal.confirmText": "您即将将活动沙盒供应商切换为 {{provider}}。",