feat(i18n): add validation strings for ValidationCard component

- Add validation section to en.json, zh.json, ja.json dictionaries
- Update ValidationCard to use useDictionary hook
- Replace all hardcoded English strings with i18n keys
This commit is contained in:
dayuan.jiang
2026-01-20 20:43:35 +09:00
parent fd9302e736
commit 011b883cdb
4 changed files with 74 additions and 18 deletions

View File

@@ -12,6 +12,7 @@ import {
} from "lucide-react" } from "lucide-react"
import Image from "next/image" import Image from "next/image"
import { useState } from "react" import { useState } from "react"
import { useDictionary } from "@/hooks/use-dictionary"
import type { ValidationResult } from "@/lib/diagram-validator" import type { ValidationResult } from "@/lib/diagram-validator"
export type ValidationStatus = export type ValidationStatus =
@@ -42,6 +43,7 @@ export function ValidationCard({
state, state,
onImproveWithSuggestions, onImproveWithSuggestions,
}: ValidationCardProps) { }: ValidationCardProps) {
const dict = useDictionary()
const [isExpanded, setIsExpanded] = useState( const [isExpanded, setIsExpanded] = useState(
state.status === "validating" || state.status === "failed", state.status === "validating" || state.status === "failed",
) )
@@ -105,7 +107,7 @@ export function ValidationCard({
switch (state.status) { switch (state.status) {
case "capturing": case "capturing":
return { return {
label: "Capturing", label: dict.validation.capturing,
color: "text-blue-600 bg-blue-50", color: "text-blue-600 bg-blue-50",
icon: ( icon: (
<div className="h-4 w-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" /> <div className="h-4 w-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" />
@@ -114,8 +116,10 @@ export function ValidationCard({
case "validating": case "validating":
return { return {
label: state.attempt label: state.attempt
? `Validating (${state.attempt}/${state.maxAttempts || 3})` ? dict.validation.validatingWithAttempt
: "Validating", .replace("{attempt}", String(state.attempt))
.replace("{max}", String(state.maxAttempts || 3))
: dict.validation.validating,
color: "text-blue-600 bg-blue-50", color: "text-blue-600 bg-blue-50",
icon: ( icon: (
<div className="h-4 w-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" /> <div className="h-4 w-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" />
@@ -123,13 +127,13 @@ export function ValidationCard({
} }
case "success": case "success":
return { return {
label: "Valid", label: dict.validation.valid,
color: "text-green-600 bg-green-50", color: "text-green-600 bg-green-50",
icon: <Check className="h-4 w-4" aria-hidden="true" />, icon: <Check className="h-4 w-4" aria-hidden="true" />,
} }
case "success_with_warnings": case "success_with_warnings":
return { return {
label: "Valid with Warnings", label: dict.validation.validWithWarnings,
color: "text-amber-600 bg-amber-50", color: "text-amber-600 bg-amber-50",
icon: ( icon: (
<AlertTriangle className="h-4 w-4" aria-hidden="true" /> <AlertTriangle className="h-4 w-4" aria-hidden="true" />
@@ -137,7 +141,7 @@ export function ValidationCard({
} }
case "failed": case "failed":
return { return {
label: "Issues Found", label: dict.validation.issuesFound,
color: "text-yellow-600 bg-yellow-50", color: "text-yellow-600 bg-yellow-50",
icon: ( icon: (
<AlertTriangle className="h-4 w-4" aria-hidden="true" /> <AlertTriangle className="h-4 w-4" aria-hidden="true" />
@@ -145,13 +149,13 @@ export function ValidationCard({
} }
case "error": case "error":
return { return {
label: "Error", label: dict.validation.error,
color: "text-red-600 bg-red-50", color: "text-red-600 bg-red-50",
icon: <X className="h-4 w-4" aria-hidden="true" />, icon: <X className="h-4 w-4" aria-hidden="true" />,
} }
case "skipped": case "skipped":
return { return {
label: "Skipped", label: dict.validation.skipped,
color: "text-gray-600 bg-gray-50", color: "text-gray-600 bg-gray-50",
icon: <Check className="h-4 w-4" aria-hidden="true" />, icon: <Check className="h-4 w-4" aria-hidden="true" />,
} }
@@ -174,7 +178,7 @@ export function ValidationCard({
/> />
</div> </div>
<span className="text-sm font-medium text-foreground/80"> <span className="text-sm font-medium text-foreground/80">
Validate Diagram {dict.validation.title}
</span> </span>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -217,7 +221,7 @@ export function ValidationCard({
className="h-3 w-3" className="h-3 w-3"
aria-hidden="true" aria-hidden="true"
/> />
Captured Screenshot: {dict.validation.capturedScreenshot}
</div> </div>
<div className="rounded-lg border border-border/50 overflow-hidden bg-white"> <div className="rounded-lg border border-border/50 overflow-hidden bg-white">
<Image <Image
@@ -236,7 +240,7 @@ export function ValidationCard({
{state.result && state.result.issues.length > 0 && ( {state.result && state.result.issues.length > 0 && (
<div> <div>
<div className="text-xs font-medium text-foreground/70 mb-2"> <div className="text-xs font-medium text-foreground/70 mb-2">
Issues Found: {dict.validation.issuesFoundLabel}
</div> </div>
<div className="space-y-2"> <div className="space-y-2">
{state.result.issues.map((issue, index) => ( {state.result.issues.map((issue, index) => (
@@ -262,7 +266,7 @@ export function ValidationCard({
{state.result && state.result.suggestions.length > 0 && ( {state.result && state.result.suggestions.length > 0 && (
<div> <div>
<div className="text-xs font-medium text-foreground/70 mb-2"> <div className="text-xs font-medium text-foreground/70 mb-2">
Suggestions: {dict.validation.suggestions}
</div> </div>
<ul className="text-xs text-foreground/60 space-y-1 list-disc list-inside"> <ul className="text-xs text-foreground/60 space-y-1 list-disc list-inside">
{state.result.suggestions.map( {state.result.suggestions.map(
@@ -278,8 +282,7 @@ export function ValidationCard({
{state.result?.valid && {state.result?.valid &&
state.result.issues.length === 0 && ( state.result.issues.length === 0 && (
<div className="text-xs text-green-600 dark:text-green-400"> <div className="text-xs text-green-600 dark:text-green-400">
Diagram passed visual validation - no issues {dict.validation.passedValidation}
detected.
</div> </div>
)} )}
</div> </div>
@@ -291,7 +294,7 @@ export function ValidationCard({
{hasRequestedImprovement ? ( {hasRequestedImprovement ? (
<div className="flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-green-600 dark:text-green-400"> <div className="flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-green-600 dark:text-green-400">
<Check className="h-4 w-4" aria-hidden="true" /> <Check className="h-4 w-4" aria-hidden="true" />
Improvement requested - check the new diagram below {dict.validation.improvementRequested}
</div> </div>
) : ( ) : (
<> <>
@@ -304,11 +307,10 @@ export function ValidationCard({
className="h-4 w-4" className="h-4 w-4"
aria-hidden="true" aria-hidden="true"
/> />
Improve with Suggestions {dict.validation.improveWithSuggestions}
</button> </button>
<p className="text-xs text-muted-foreground mt-2 text-center"> <p className="text-xs text-muted-foreground mt-2 text-center">
Regenerate the diagram using the validation {dict.validation.regenerateWithFeedback}
feedback
</p> </p>
</> </>
)} )}

View File

@@ -252,6 +252,24 @@
"searchPlaceholder": "Search chats...", "searchPlaceholder": "Search chats...",
"noResults": "No chats found" "noResults": "No chats found"
}, },
"validation": {
"title": "Validate Diagram",
"capturing": "Capturing",
"validating": "Validating",
"validatingWithAttempt": "Validating ({attempt}/{max})",
"valid": "Valid",
"validWithWarnings": "Valid with Warnings",
"issuesFound": "Issues Found",
"error": "Error",
"skipped": "Skipped",
"capturedScreenshot": "Captured Screenshot:",
"issuesFoundLabel": "Issues Found:",
"suggestions": "Suggestions:",
"passedValidation": "Diagram passed visual validation - no issues detected.",
"improvementRequested": "Improvement requested - check the new diagram below",
"improveWithSuggestions": "Improve with Suggestions",
"regenerateWithFeedback": "Regenerate the diagram using the validation feedback"
},
"modelConfig": { "modelConfig": {
"title": "AI Model Configuration", "title": "AI Model Configuration",
"description": "Configure multiple AI providers and models", "description": "Configure multiple AI providers and models",

View File

@@ -252,6 +252,24 @@
"searchPlaceholder": "チャットを検索...", "searchPlaceholder": "チャットを検索...",
"noResults": "チャットが見つかりません" "noResults": "チャットが見つかりません"
}, },
"validation": {
"title": "ダイアグラムを検証",
"capturing": "キャプチャ中",
"validating": "検証中",
"validatingWithAttempt": "検証中 ({attempt}/{max})",
"valid": "有効",
"validWithWarnings": "有効(警告あり)",
"issuesFound": "問題が見つかりました",
"error": "エラー",
"skipped": "スキップ",
"capturedScreenshot": "キャプチャした画像:",
"issuesFoundLabel": "検出された問題:",
"suggestions": "提案:",
"passedValidation": "ダイアグラムは視覚検証に合格しました - 問題は検出されませんでした。",
"improvementRequested": "改善リクエスト済み - 下の新しいダイアグラムを確認してください",
"improveWithSuggestions": "提案で改善",
"regenerateWithFeedback": "検証フィードバックを使用してダイアグラムを再生成"
},
"modelConfig": { "modelConfig": {
"title": "AIモデル設定", "title": "AIモデル設定",
"description": "複数のAIプロバイダーとモデルを設定", "description": "複数のAIプロバイダーとモデルを設定",

View File

@@ -252,6 +252,24 @@
"searchPlaceholder": "搜索对话...", "searchPlaceholder": "搜索对话...",
"noResults": "未找到对话" "noResults": "未找到对话"
}, },
"validation": {
"title": "验证图表",
"capturing": "截图中",
"validating": "验证中",
"validatingWithAttempt": "验证中 ({attempt}/{max})",
"valid": "通过",
"validWithWarnings": "通过(有警告)",
"issuesFound": "发现问题",
"error": "错误",
"skipped": "已跳过",
"capturedScreenshot": "截图预览:",
"issuesFoundLabel": "发现的问题:",
"suggestions": "建议:",
"passedValidation": "图表通过视觉验证 - 未发现问题。",
"improvementRequested": "改进请求已发送 - 请查看下方新图表",
"improveWithSuggestions": "根据建议改进",
"regenerateWithFeedback": "使用验证反馈重新生成图表"
},
"modelConfig": { "modelConfig": {
"title": "AI 模型配置", "title": "AI 模型配置",
"description": "配置多个 AI 提供商和模型", "description": "配置多个 AI 提供商和模型",