fix(ui): i18n audit repair round 4

This commit is contained in:
吹雪 2026-06-11 08:48:17 +09:00
parent 47d422c745
commit 43bbc47820
15 changed files with 114 additions and 51 deletions

View file

@ -193,7 +193,7 @@ const MakeAgentPublicForm: React.FC<MakeAgentPublicFormProps> = ({
<div className="bg-yellow-50 border border-yellow-200 rounded-lg p-4">
<Text className="text-sm text-yellow-800">
<strong>Warning:</strong>{" "}
<strong>{t("common.warning")}:</strong>{" "}
<Trans i18nKey="aiHub.makeAgentPublicForm.warningText" components={{ code: <code key="code" /> }} />
</Text>
</div>

View file

@ -276,10 +276,10 @@ const DefaultUserSettings: React.FC<DefaultUserSettingsProps> = ({
className="mt-2"
>
<Option key="no-default-models" value="no-default-models">
No Default Models
{t("defaultUserSettings.noDefaultModels")}
</Option>
<Option key="all-proxy-models" value="all-proxy-models">
All Proxy Models
{t("defaultUserSettings.allProxyModels")}
</Option>
{availableModels.map((model: string) => (
<Option key={model} value={model}>

View file

@ -119,7 +119,9 @@ export function EvaluationSettingsModal({
<label className="block text-sm font-medium text-gray-700 mb-1.5">
{t("guardrailsMonitor.evaluationSettingsModal.schemaLabel")}
</label>
<p className="text-xs text-gray-400 mb-1">response_format: json_schema</p>
<p className="text-xs text-gray-400 mb-1">
{t("guardrailsMonitor.evaluationSettingsModal.responseFormatHint")}
</p>
<Input.TextArea
value={schema}
onChange={(e) => setSchema(e.target.value)}

View file

@ -116,7 +116,7 @@ export function ProjectDetail({ projectId, onBack }: ProjectDetailProps) {
</Tag>
</Flex>
<Text type="secondary">
ID: <Text copyable>{project.project_id}</Text>
{t("projects.projectDetailsPage.id")} <Text copyable>{project.project_id}</Text>
</Text>
</div>
</div>
@ -255,7 +255,7 @@ export function ProjectDetail({ projectId, onBack }: ProjectDetailProps) {
</Text>
<br />
<Text type="secondary" style={{ fontSize: 12 }}>
ID:{" "}
{t("projects.projectDetailsPage.id")}{" "}
<Text copyable style={{ fontSize: 12 }}>
{teamInfo.team_id}
</Text>

View file

@ -273,7 +273,7 @@ const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = fals
<button
onClick={handleClose}
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700 focus:outline-none"
aria-label="Close"
aria-label={t("common.close")}
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />

View file

@ -129,16 +129,20 @@ const ComplexityRouterConfig: React.FC<ComplexityRouterConfigProps> = ({ modelIn
</Text>
<ul style={{ marginTop: 8, marginBottom: 0, paddingLeft: 20, fontSize: 13, color: "rgba(0, 0, 0, 0.45)" }}>
<li>
<strong>SIMPLE</strong>: Score &lt; 0.15
<strong>SIMPLE</strong>
{t("addModel.complexityRouterConfig.scoreRangeSimple")}
</li>
<li>
<strong>MEDIUM</strong>: Score 0.15 - 0.35
<strong>MEDIUM</strong>
{t("addModel.complexityRouterConfig.scoreRangeMedium")}
</li>
<li>
<strong>COMPLEX</strong>: Score 0.35 - 0.60
<strong>COMPLEX</strong>
{t("addModel.complexityRouterConfig.scoreRangeComplex")}
</li>
<li>
<strong>REASONING</strong>: Score &gt; 0.60 (or 2+ reasoning markers)
<strong>REASONING</strong>
{t("addModel.complexityRouterConfig.scoreRangeReasoning")}
</li>
</ul>
</Card>

View file

@ -333,7 +333,9 @@ function AssistantBubble({ message, isLastMessage, isStreaming, isTypingIndicato
>
{mainContent}
</ReactMarkdown>
{stoppedSuffix && <span style={{ color: "#9ca3af", fontStyle: "italic" }}> [stopped]</span>}
{stoppedSuffix && (
<span style={{ color: "#9ca3af", fontStyle: "italic" }}> {t("chat.chatMessages.streamStopped")}</span>
)}
</div>
<CopyButton text={mainContent} />

View file

@ -160,9 +160,9 @@ const PassThroughGuardrailsSection: React.FC<PassThroughGuardrailsSectionProps>
</div>
<div className="text-xs space-y-1">
<div>{t("commonComponents.passThroughGuardrailsSection.examples")}</div>
<div>• query</div>
<div>• documents[*].text</div>
<div>• messages[*].content</div>
<div>{t("commonComponents.passThroughGuardrailsSection.tooltipExampleQuery")}</div>
<div>{t("commonComponents.passThroughGuardrailsSection.tooltipExampleDocuments")}</div>
<div>{t("commonComponents.passThroughGuardrailsSection.tooltipExampleMessages")}</div>
</div>
</div>
}
@ -180,7 +180,7 @@ const PassThroughGuardrailsSection: React.FC<PassThroughGuardrailsSectionProps>
className="text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50"
disabled={disabled}
>
+ query
{t("commonComponents.passThroughGuardrailsSection.addQueryButton")}
</button>
<button
type="button"
@ -191,7 +191,7 @@ const PassThroughGuardrailsSection: React.FC<PassThroughGuardrailsSectionProps>
className="text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50"
disabled={disabled}
>
+ documents[*]
{t("commonComponents.passThroughGuardrailsSection.addDocumentsButton")}
</button>
</div>
</div>
@ -217,8 +217,8 @@ const PassThroughGuardrailsSection: React.FC<PassThroughGuardrailsSectionProps>
</div>
<div className="text-xs space-y-1">
<div>{t("commonComponents.passThroughGuardrailsSection.examples")}</div>
<div>• results[*].text</div>
<div>• choices[*].message.content</div>
<div>{t("commonComponents.passThroughGuardrailsSection.tooltipExampleResults")}</div>
<div>{t("commonComponents.passThroughGuardrailsSection.tooltipExampleChoices")}</div>
</div>
</div>
}
@ -236,7 +236,7 @@ const PassThroughGuardrailsSection: React.FC<PassThroughGuardrailsSectionProps>
className="text-xs px-2 py-1 bg-white border border-gray-300 rounded hover:bg-gray-50"
disabled={disabled}
>
+ results[*]
{t("commonComponents.passThroughGuardrailsSection.addResultsButton")}
</button>
</div>
</div>

View file

@ -193,8 +193,8 @@ const GuardrailProviderFields: React.FC<GuardrailProviderFieldsProps> = ({
</Select>
) : field.type === "bool" || field.type === "boolean" ? (
<Select placeholder={field.description}>
<Select.Option value={true}>True</Select.Option>
<Select.Option value={false}>False</Select.Option>
<Select.Option value={true}>{t("guardrails.guardrailProviderFields.trueLabel")}</Select.Option>
<Select.Option value={false}>{t("guardrails.guardrailProviderFields.falseLabel")}</Select.Option>
</Select>
) : field.type === "percentage" && field.min != null && field.max != null ? (
<Slider

View file

@ -198,7 +198,7 @@ function CreateToolsetModal({ open, onClose, onSave, accessToken, initialToolset
rules={[{ required: true, message: t("mcpTools.mCPToolsetsTab.toolsetNameRequired") }]}
className="flex-1 mb-0"
>
<Input placeholder="e.g. github-linear-tools" />
<Input placeholder={t("mcpTools.mCPToolsetsTab.toolsetNamePlaceholder")} />
</Form.Item>
<Form.Item label={t("common.description")} name="description" className="flex-1 mb-0">
<Input placeholder={t("mcpTools.mCPToolsetsTab.descriptionPlaceholder")} />

View file

@ -98,7 +98,7 @@ const MCPDiscovery: React.FC<MCPDiscoveryProps> = ({
<div className="flex items-center space-x-3">
<img
src={mcpLogoImg}
alt="MCP Logo"
alt={t("mcpTools.mcpDiscovery.mcpLogoAlt")}
className="w-8 h-8 object-contain"
style={{
height: "20px",

View file

@ -452,7 +452,9 @@ const AiSuggestionModal: React.FC<AiSuggestionModalProps> = ({
: "bg-amber-50 text-amber-600 border-amber-200"
}`}
>
+{template.estimated_latency_ms <= 1 ? "<1" : template.estimated_latency_ms}ms latency
{t("policies.aiSuggestionModal.msLatencyDisplay", {
value: template.estimated_latency_ms <= 1 ? "<1" : template.estimated_latency_ms,
})}
</span>
</Tooltip>
)}

View file

@ -148,13 +148,14 @@ const TruncatedValue: React.FC<{ value: string }> = ({ value }) => {
// ── metadata card ─────────────────────────────────────────────────────────────
const MetadataCard: React.FC<{ run: WorkflowRun }> = ({ run }) => {
const { t } = useTranslation();
const meta = run.metadata ?? {};
const primaryFields: { key: string; label: string }[] = [
{ key: "state", label: "state" },
{ key: "worktree_path", label: "worktree" },
{ key: "grill_session_id", label: "grill session" },
{ key: "session_id", label: "session" },
{ key: "state", label: t("workflowRuns.index.metaState") },
{ key: "worktree_path", label: t("workflowRuns.index.metaWorktree") },
{ key: "grill_session_id", label: t("workflowRuns.index.grillSession") },
{ key: "session_id", label: t("workflowRuns.index.metaSession") },
];
const primaryKeys = new Set(["title", ...primaryFields.map((f) => f.key)]);

View file

@ -316,7 +316,15 @@
"responseFieldsTooltipTitle": "Specify which response fields to check",
"examples": "Examples:",
"requestFieldsPlaceholder": "Type field name or use + buttons above (e.g., query, documents[*].text)",
"responseFieldsPlaceholder": "Type field name or use + buttons above (e.g., results[*].text)"
"responseFieldsPlaceholder": "Type field name or use + buttons above (e.g., results[*].text)",
"tooltipExampleQuery": "• query",
"tooltipExampleDocuments": "• documents[*].text",
"tooltipExampleMessages": "• messages[*].content",
"addQueryButton": "+ query",
"addDocumentsButton": "+ documents[*]",
"tooltipExampleResults": "• results[*].text",
"tooltipExampleChoices": "• choices[*].message.content",
"addResultsButton": "+ results[*]"
},
"passThroughSecuritySection": {
"title": "Security",
@ -556,7 +564,9 @@
"notifications": {
"fetchFailed": "Failed to fetch SSO settings",
"updateFailed": "Failed to update settings: {{error}}"
}
},
"noDefaultModels": "No Default Models",
"allProxyModels": "All Proxy Models"
},
"guardrailSettingsView": {
"noGuardrailsConfigured": "No guardrails configured",
@ -1892,7 +1902,9 @@
"loadFailed": "Failed to load provider parameters",
"loadingTip": "Loading provider parameters...",
"noFields": "No configuration fields available for this provider.",
"fieldRequired": "{{fieldKey}} is required"
"fieldRequired": "{{fieldKey}} is required",
"trueLabel": "True",
"falseLabel": "False"
},
"guardrailTable": {
"colGuardrailId": "Guardrail ID",
@ -3549,7 +3561,8 @@
"howToolsetsWorkDesc1": "Create a toolset, assign it to a key via",
"howToolsetsWorkPath": "API Keys → Edit Key → MCP Servers",
"howToolsetsWorkDesc2": ", then point your MCP client at the toolset URL. The client only sees the tools you picked.",
"configLabel": "Claude Code / Cursor config"
"configLabel": "Claude Code / Cursor config",
"toolsetNamePlaceholder": "e.g. github-linear-tools"
},
"oAuthFormFields": {
"leaveBlankToKeep": "leave blank to keep existing",
@ -3786,7 +3799,8 @@
"failedToLoadServers": "Failed to load MCP servers",
"failedToLoadServersError": "Failed to load servers: {{error}}",
"noServersFound": "No servers found.",
"addCustomServer": "Add a custom server"
"addCustomServer": "Add a custom server",
"mcpLogoAlt": "MCP Logo"
},
"mcpServerCostConfig": {
"title": "Cost Configuration",
@ -5031,7 +5045,8 @@
"noTestableGuardrails": "No testable guardrails in selected templates.",
"testSuggestions": "Test Suggestions",
"useSelectedTemplates_one": "Use {{count}} Selected Template",
"useSelectedTemplates_other": "Use {{count}} Selected Templates"
"useSelectedTemplates_other": "Use {{count}} Selected Templates",
"msLatencyDisplay": "+{{value}}ms latency"
},
"attachmentTable": {
"attachmentId": "Attachment ID",
@ -5440,7 +5455,11 @@
"examplesLabel": "Examples: {{examples}}",
"selectModelPlaceholder": "Select model for {{label}} queries",
"howClassificationWorksTitle": "How Classification Works",
"howClassificationWorksDesc": "The router scores each request across 7 dimensions: token count, code presence, reasoning markers, technical terms, simple indicators, multi-step patterns, and question complexity. The weighted score determines the tier:"
"howClassificationWorksDesc": "The router scores each request across 7 dimensions: token count, code presence, reasoning markers, technical terms, simple indicators, multi-step patterns, and question complexity. The weighted score determines the tier:",
"scoreRangeSimple": ": Score < 0.15",
"scoreRangeMedium": ": Score 0.15 - 0.35",
"scoreRangeComplex": ": Score 0.35 - 0.60",
"scoreRangeReasoning": ": Score > 0.60 (or 2+ reasoning markers)"
},
"routerConfigBuilder": {
"title": "Routes Configuration",
@ -6980,7 +6999,8 @@
"spendLabel": "Spend",
"unlimited": "Unlimited",
"membersLabel": "Members",
"noTeamAssigned": "No team assigned"
"noTeamAssigned": "No team assigned",
"id": "ID:"
},
"projectKeysSection": {
"title": "Keys",
@ -7066,7 +7086,8 @@
"selectModel": "Select a model",
"signInToSeeModels": "Sign in to see models",
"noModelsAvailable": "No models available",
"runEvaluation": "Run Evaluation"
"runEvaluation": "Run Evaluation",
"responseFormatHint": "response_format: json_schema"
},
"guardrailConfig": {
"current": "current",
@ -7159,7 +7180,8 @@
"thinking": "Thinking...",
"toolCall": "Tool call",
"arguments": "Arguments",
"result": "Result"
"result": "Result",
"streamStopped": "[stopped]"
},
"chatPage": {
"goodMorning": "Good morning",
@ -8586,7 +8608,11 @@
"noEvents": "No events recorded",
"noMessages": "No messages",
"less": "less",
"more": "more"
"more": "more",
"grillSession": "grill session",
"metaState": "state",
"metaWorktree": "worktree",
"metaSession": "session"
}
},
"pages": {

View file

@ -316,7 +316,15 @@
"responseFieldsTooltipTitle": "指定要检查的响应字段",
"examples": "示例:",
"requestFieldsPlaceholder": "输入字段名或使用上方 + 按钮(如:query、documents[*].text)",
"responseFieldsPlaceholder": "输入字段名或使用上方 + 按钮(如:results[*].text)"
"responseFieldsPlaceholder": "输入字段名或使用上方 + 按钮(如:results[*].text)",
"tooltipExampleQuery": "• query",
"tooltipExampleDocuments": "• documents[*].text",
"tooltipExampleMessages": "• messages[*].content",
"addQueryButton": "+ query",
"addDocumentsButton": "+ documents[*]",
"tooltipExampleResults": "• results[*].text",
"tooltipExampleChoices": "• choices[*].message.content",
"addResultsButton": "+ results[*]"
},
"passThroughSecuritySection": {
"title": "安全",
@ -556,7 +564,9 @@
"notifications": {
"fetchFailed": "获取 SSO 设置失败",
"updateFailed": "更新设置失败:{{error}}"
}
},
"noDefaultModels": "无默认模型",
"allProxyModels": "所有代理模型"
},
"guardrailSettingsView": {
"noGuardrailsConfigured": "未配置护栏",
@ -1892,7 +1902,9 @@
"loadFailed": "加载提供商参数失败",
"loadingTip": "正在加载提供商参数...",
"noFields": "此提供商暂无可配置字段。",
"fieldRequired": "{{fieldKey}} 为必填项"
"fieldRequired": "{{fieldKey}} 为必填项",
"trueLabel": "是",
"falseLabel": "否"
},
"guardrailTable": {
"colGuardrailId": "护栏 ID",
@ -3549,7 +3561,8 @@
"howToolsetsWorkDesc1": "创建工具集,通过",
"howToolsetsWorkPath": "API 密钥 → 编辑密钥 → MCP 服务器",
"howToolsetsWorkDesc2": "将其分配给密钥,然后将您的 MCP 客户端指向工具集 URL。客户端只会看到您选定的工具。",
"configLabel": "Claude Code / Cursor 配置"
"configLabel": "Claude Code / Cursor 配置",
"toolsetNamePlaceholder": "例如:github-linear-tools"
},
"oAuthFormFields": {
"leaveBlankToKeep": "留空以保留现有值",
@ -3786,7 +3799,8 @@
"failedToLoadServers": "加载 MCP 服务器失败",
"failedToLoadServersError": "加载服务器失败:{{error}}",
"noServersFound": "未找到服务器。",
"addCustomServer": "添加自定义服务器"
"addCustomServer": "添加自定义服务器",
"mcpLogoAlt": "MCP Logo"
},
"mcpServerCostConfig": {
"title": "费用配置",
@ -5031,7 +5045,8 @@
"noTestableGuardrails": "所选模板中没有可测试的护栏。",
"testSuggestions": "测试建议",
"useSelectedTemplates_one": "使用 {{count}} 个选中的模板",
"useSelectedTemplates_other": "使用 {{count}} 个选中的模板"
"useSelectedTemplates_other": "使用 {{count}} 个选中的模板",
"msLatencyDisplay": "+{{value}}ms 延迟"
},
"attachmentTable": {
"attachmentId": "附件 ID",
@ -5440,7 +5455,11 @@
"examplesLabel": "示例:{{examples}}",
"selectModelPlaceholder": "为{{label}}查询选择模型",
"howClassificationWorksTitle": "分类原理",
"howClassificationWorksDesc": "路由器从 7 个维度对每个请求进行评分:Token 数量、代码存在性、推理标记、技术术语、简单指标、多步骤模式和问题复杂度。加权分数决定层级:"
"howClassificationWorksDesc": "路由器从 7 个维度对每个请求进行评分:Token 数量、代码存在性、推理标记、技术术语、简单指标、多步骤模式和问题复杂度。加权分数决定层级:",
"scoreRangeSimple": ":评分 < 0.15",
"scoreRangeMedium": ":评分 0.15 - 0.35",
"scoreRangeComplex": ":评分 0.35 - 0.60",
"scoreRangeReasoning": ":评分 > 0.60(或含 2+ 个推理标记)"
},
"routerConfigBuilder": {
"title": "路由配置",
@ -6980,7 +6999,8 @@
"spendLabel": "花费",
"unlimited": "无限制",
"membersLabel": "成员",
"noTeamAssigned": "未分配团队"
"noTeamAssigned": "未分配团队",
"id": "ID:"
},
"projectKeysSection": {
"title": "密钥",
@ -7066,7 +7086,8 @@
"selectModel": "选择模型",
"signInToSeeModels": "请登录以查看可用模型",
"noModelsAvailable": "暂无可用模型",
"runEvaluation": "运行评估"
"runEvaluation": "运行评估",
"responseFormatHint": "response_format: json_schema"
},
"guardrailConfig": {
"current": "当前",
@ -7159,7 +7180,8 @@
"thinking": "思考中...",
"toolCall": "工具调用",
"arguments": "参数",
"result": "结果"
"result": "结果",
"streamStopped": "[已停止]"
},
"chatPage": {
"goodMorning": "早上好",
@ -8586,7 +8608,11 @@
"noEvents": "暂无事件记录",
"noMessages": "暂无消息",
"less": "收起",
"more": "展开"
"more": "展开",
"grillSession": "grill session",
"metaState": "状态",
"metaWorktree": "工作树",
"metaSession": "会话"
}
},
"pages": {