fix(i18n): Wave 3 清零 - status-orb + OmniTerminal + sse-states

- status-orb.tsx: 狀態 label 改用 useTranslations
- OmniTerminal.tsx: 'SSE Live'/'Offline' 改用 i18n
- sse-states.ts: label 改為 i18n key (connection.xxx)
- 新增 subscribing/streaming 翻譯

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-29 16:30:01 +08:00
parent 590b5c2bd5
commit 9747bd43a2
5 changed files with 35 additions and 14 deletions

View File

@@ -153,7 +153,9 @@
"connection": {
"disconnected": "Disconnected",
"connecting": "Connecting...",
"subscribing": "Subscribing...",
"connected": "Live",
"streaming": "Streaming",
"reconnecting": "Reconnecting...",
"error": "Connection Error",
"mockMode": "MOCK"

View File

@@ -153,7 +153,9 @@
"connection": {
"disconnected": "已斷線",
"connecting": "連線中...",
"subscribing": "訂閱中...",
"connected": "即時",
"streaming": "串流中",
"reconnecting": "重新連線...",
"error": "連線錯誤",
"mockMode": "模擬"

View File

@@ -1,5 +1,13 @@
'use client'
/**
* StatusOrb - Agent 狀態指示燈
* ============================
* i18n: 100% 使用 useTranslations
* 修復: 2026-03-29 Wave 3 i18n 清零
*/
import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
type AgentStatus = 'idle' | 'thinking' | 'executing' | 'waiting_approval'
@@ -10,25 +18,29 @@ interface StatusOrbProps {
className?: string
}
const statusConfig: Record<AgentStatus, { color: string; label: string; animate: boolean }> = {
// i18n key 對應表
const statusI18nKey: Record<AgentStatus, string> = {
idle: 'idle',
thinking: 'thinking',
executing: 'executing',
waiting_approval: 'waitingApproval',
}
const statusConfig: Record<AgentStatus, { color: string; animate: boolean }> = {
idle: {
color: 'bg-nothing-gray-600',
label: 'Idle',
animate: false,
},
thinking: {
color: 'bg-status-warning',
label: 'Thinking',
animate: true,
},
executing: {
color: 'bg-status-healthy',
label: 'Executing',
animate: true,
},
waiting_approval: {
color: 'bg-status-critical',
label: 'Awaiting Approval',
animate: true,
},
}
@@ -40,8 +52,10 @@ const sizeConfig = {
}
export function StatusOrb({ status, size = 'md', className }: StatusOrbProps) {
const t = useTranslations('status')
const config = statusConfig[status]
const sizeClass = sizeConfig[size]
const label = t(statusI18nKey[status])
return (
<div className={cn('relative', className)}>
@@ -70,7 +84,7 @@ export function StatusOrb({ status, size = 'md', className }: StatusOrbProps) {
{/* Label */}
<div className="absolute -bottom-6 left-1/2 -translate-x-1/2 whitespace-nowrap">
<span className="font-mono text-xs text-nothing-gray-500">
{config.label}
{label}
</span>
</div>
</div>

View File

@@ -205,7 +205,7 @@ export const OmniTerminal = () => {
</span>
<div className="flex items-center gap-1 opacity-60">
<span className={`w-2 h-2 rounded-full ${isConnected ? 'bg-green-500' : 'bg-gray-400'}`}></span>
<span className="text-xs uppercase font-mono hidden sm:inline">{isConnected ? 'SSE Live' : 'Offline'}</span>
<span className="text-xs uppercase font-mono hidden sm:inline">{isConnected ? t('sseLive') : t('offline')}</span>
</div>
</div>
<button

View File

@@ -109,10 +109,13 @@ export interface SSEStateInfo {
/**
* 狀態資訊對照表
*
* Note: label 是 i18n key (connection.xxx),使用時需呼叫 t(label)
* 修復: 2026-03-29 Wave 3 i18n 清零
*/
export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
disconnected: {
label: 'Offline',
label: 'disconnected', // i18n: connection.disconnected
isLoading: false,
isConnected: false,
isStreaming: false,
@@ -120,7 +123,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-gray-400',
},
connecting: {
label: 'Connecting...',
label: 'connecting', // i18n: connection.connecting
isLoading: true,
isConnected: false,
isStreaming: false,
@@ -128,7 +131,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-yellow-500',
},
subscribing: {
label: 'Subscribing...',
label: 'subscribing', // i18n: connection.subscribing
isLoading: true,
isConnected: false,
isStreaming: false,
@@ -136,7 +139,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-yellow-500',
},
connected: {
label: 'SSE Live',
label: 'connected', // i18n: connection.connected
isLoading: false,
isConnected: true,
isStreaming: false,
@@ -144,7 +147,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-green-500',
},
streaming: {
label: 'Streaming',
label: 'streaming', // i18n: connection.streaming
isLoading: false,
isConnected: true,
isStreaming: true,
@@ -152,7 +155,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-claw-blue',
},
reconnecting: {
label: 'Reconnecting...',
label: 'reconnecting', // i18n: connection.reconnecting
isLoading: true,
isConnected: false,
isStreaming: false,
@@ -160,7 +163,7 @@ export const SSE_STATE_INFO: Record<SSEConnectionState, SSEStateInfo> = {
color: 'text-orange-500',
},
error: {
label: 'Error',
label: 'error', // i18n: connection.error
isLoading: false,
isConnected: false,
isStreaming: false,