fix(frontend): 补齐英文失败路径

This commit is contained in:
2026-09-05 09:48:27 +08:00
parent ef961d322b
commit 89e475c0c2
17 changed files with 83 additions and 70 deletions
+2 -1
View File
@@ -3,6 +3,7 @@ import { ref, computed } from 'vue'
import type { AgentRun, AgentEvent, ToolDefinition, PermissionRequest, ToolCall } from '@/contracts'
import * as agentService from '@/services/agentService'
import type { SseClient } from '@/services/sseClient'
import { t } from '@/i18n'
export const useAgentStore = defineStore('agent', () => {
const runs = ref<AgentRun[]>([])
@@ -93,7 +94,7 @@ export const useAgentStore = defineStore('agent', () => {
tool_name: String(call.name ?? 'unknown'),
permission: String(data.permission ?? ''),
parameters: (call.arguments ?? {}) as Record<string, unknown>,
impact: '该工具需要获得权限后才能继续执行。',
impact: t('该工具需要获得权限后才能继续执行。', 'This tool requires permission before it can continue.'),
}
if (run) run.status = 'waiting_permission'
} else if (['RunCompleted', 'RunFailed', 'RunCancelled'].includes(event.event)) {
+4 -3
View File
@@ -3,6 +3,7 @@ import { ref, computed, reactive } from 'vue'
import type { ChatMessage, Conversation } from '@/contracts'
import { streamChat } from '@/services/chatService'
import type { SseClient } from '@/services/sseClient'
import { t } from '@/i18n'
export const useChatStore = defineStore('chat', () => {
const conversations = ref<Conversation[]>([])
@@ -128,11 +129,11 @@ export const useChatStore = defineStore('chat', () => {
content: String(event.data.content ?? event.data.snippet ?? ''),
})
}
if (event.event === 'Error') aiMsg.content += `\n\n生成失败:${String(event.data.message ?? '未知错误')}`
if (event.event === 'Error') aiMsg.content += `\n\n${t('生成失败:', 'Generation failed: ')}${String(event.data.message ?? t('未知错误', 'Unknown error'))}`
},
onError(error) {
if (version !== streamVersion) return
aiMsg.content += `\n\n连接失败:${error.message}`
aiMsg.content += `\n\n${t('连接失败:', 'Connection failed: ')}${error.message}`
isStreaming.value = false
sseClient = null
},
@@ -162,7 +163,7 @@ export const useChatStore = defineStore('chat', () => {
stopGeneration()
const newConv: Conversation = {
conversation_id: crypto.randomUUID(),
title: '新对话',
title: t('新对话', 'New conversation'),
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
message_count: 0,
+3 -2
View File
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { SaveStatus } from '@/contracts'
import * as workspaceService from '@/services/workspaceService'
import { t } from '@/i18n'
export const useEditorStore = defineStore('editor', () => {
const mode = ref<'wysiwyg' | 'source'>('wysiwyg')
@@ -76,12 +77,12 @@ export const useEditorStore = defineStore('editor', () => {
saveTimer = null
}
if (saveStatus.value === 'conflict') {
throw new Error('当前文件存在编辑冲突,请处理后再切换文件。')
throw new Error(t('当前文件存在编辑冲突,请处理后再切换文件。', 'The current file has an editing conflict. Resolve it before switching files.'))
}
if (pendingSave) await pendingSave
if (saveStatus.value === 'dirty' || saveStatus.value === 'save_failed') await save()
if (saveStatus.value === 'dirty' || saveStatus.value === 'save_failed') {
throw new Error('当前文件保存失败,已阻止切换以避免内容丢失。')
throw new Error(t('当前文件保存失败,已阻止切换以避免内容丢失。', 'The current file could not be saved. Switching was blocked to prevent data loss.'))
}
// 版本号使较慢的旧读取不能覆盖用户后选择的新文件。
const version = ++loadVersion
+2 -1
View File
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Plugin } from '@/contracts'
import * as pluginService from '@/services/pluginService'
import { t } from '@/i18n'
export const usePluginStore = defineStore('plugin', () => {
const plugins = ref<Plugin[]>([])
@@ -23,7 +24,7 @@ export const usePluginStore = defineStore('plugin', () => {
plugins.value = await pluginService.listPlugins()
error.value = null
} catch (reason) {
error.value = reason instanceof Error ? reason.message : 'Plugin 加载失败'
error.value = reason instanceof Error ? reason.message : t('Plugin 加载失败', 'Failed to load Plugins')
} finally {
isLoading.value = false
}
+6 -5
View File
@@ -3,6 +3,7 @@ import { ref, computed } from 'vue'
import type { ProviderConfig, ModelInfo, ProviderPreset } from '@/contracts'
import { createProvider, deleteProvider as deleteProviderRequest, getCredentialStatus, listModels, listProviderPresets, listProviders, putCredential, testProvider as testProviderRequest, updateProvider as updateProviderRequest } from '@/services/providerService'
import { ApiErrorClass } from '@/services/apiClient'
import { t } from '@/i18n'
export const useProviderStore = defineStore('provider', () => {
const providers = ref<ProviderConfig[]>([])
@@ -29,7 +30,7 @@ export const useProviderStore = defineStore('provider', () => {
}
error.value = null
} catch (reason) {
error.value = reason instanceof Error ? reason.message : 'Provider 加载失败'
error.value = reason instanceof Error ? reason.message : t('Provider 加载失败', 'Failed to load Providers')
} finally {
isLoading.value = false
}
@@ -39,7 +40,7 @@ export const useProviderStore = defineStore('provider', () => {
try {
presets.value = await listProviderPresets()
} catch (reason) {
error.value = reason instanceof Error ? reason.message : 'Provider 预设加载失败'
error.value = reason instanceof Error ? reason.message : t('Provider 预设加载失败', 'Failed to load Provider presets')
}
}
@@ -55,11 +56,11 @@ export const useProviderStore = defineStore('provider', () => {
} catch (reason) {
const provider = providers.value.find((item) => item.provider_id === providerId)
const credentialId = provider?.credential_id
let message = reason instanceof Error ? reason.message : '模型列表获取失败'
let message = reason instanceof Error ? reason.message : t('模型列表获取失败', 'Failed to load the model list')
if (reason instanceof ApiErrorClass && reason.code === 'PROVIDER_CREDENTIAL_MISSING') {
message = '尚未配置 API Key,请编辑该 Provider 后填写并保存。'
message = t('尚未配置 API Key,请编辑该 Provider 后填写并保存。', 'No API key is configured. Edit this Provider, enter a key, and save it.')
} else if (reason instanceof ApiErrorClass && reason.code === 'PROVIDER_AUTH_FAILED') {
message = `鉴权失败,请检查凭据“${credentialId || '未设置'}”对应的 API Key 是否有效。`
message = t(`鉴权失败,请检查凭据“${credentialId || '未设置'}”对应的 API Key 是否有效。`, `Authentication failed. Check the API key for credential “${credentialId || 'not set'}”.`)
}
modelErrorsByProvider.value[providerId] = message
throw reason
+5 -4
View File
@@ -3,6 +3,7 @@ import { ref } from 'vue'
import type { SearchResult, SearchRequest } from '@/contracts'
import * as searchService from '@/services/searchService'
import { ApiErrorClass } from '@/services/apiClient'
import { t } from '@/i18n'
const VECTOR_ERROR_CODES = new Set([
'SEMANTIC_INDEX_UNAVAILABLE',
@@ -28,7 +29,7 @@ export const useSearchStore = defineStore('search', () => {
if (version !== historyVersion) return
recentQueries.value = response.queries
historyError.value = ''
} catch { if (version === historyVersion) historyError.value = '无法读取应用搜索记录,请检查后端连接。' }
} catch { if (version === historyVersion) historyError.value = t('无法读取应用搜索记录,请检查后端连接。', 'Could not load search history. Check the backend connection.') }
}
async function clearHistory() {
const version = ++historyVersion
@@ -36,7 +37,7 @@ export const useSearchStore = defineStore('search', () => {
await searchService.clearHistory()
if (version !== historyVersion) return
recentQueries.value = []; historyError.value = ''
} catch { if (version === historyVersion) historyError.value = '清空搜索记录失败,请重试。' }
} catch { if (version === historyVersion) historyError.value = t('清空搜索记录失败,请重试。', 'Failed to clear search history. Please retry.') }
}
const error = ref<string | null>(null)
const vectorUnavailable = ref(false)
@@ -71,12 +72,12 @@ export const useSearchStore = defineStore('search', () => {
selectedIndex.value = 0
} catch (fallbackError) {
if (version !== searchVersion) return
error.value = fallbackError instanceof Error ? fallbackError.message : '全文检索降级失败'
error.value = fallbackError instanceof Error ? fallbackError.message : t('全文检索降级失败', 'Full-text search fallback failed')
results.value = []
total.value = 0
}
} else {
error.value = reason instanceof Error ? reason.message : '搜索失败'
error.value = reason instanceof Error ? reason.message : t('搜索失败', 'Search failed')
results.value = []
total.value = 0
}
+5 -5
View File
@@ -5,7 +5,7 @@ import { resolveApiUrl } from '@/services/apiClient'
import packageInfo from '../../package.json'
import * as indexService from '@/services/indexService'
import * as systemService from '@/services/systemService'
import { appLocale } from '@/i18n'
import { appLocale, t } from '@/i18n'
export const useSettingsStore = defineStore('settings', () => {
const saved = (() => {
@@ -17,7 +17,7 @@ export const useSettingsStore = defineStore('settings', () => {
const autoSaveInterval = ref(typeof saved.autoSaveInterval === 'number' ? saved.autoSaveInterval : 1500)
const language = appLocale
const appVersion = ref(packageInfo.version)
const aiCoreVersion = ref('未获取')
const aiCoreVersion = ref('')
// Editor
const defaultEditorMode = ref<'wysiwyg' | 'source'>(saved.defaultEditorMode === 'source' ? 'source' : 'wysiwyg')
@@ -48,10 +48,10 @@ export const useSettingsStore = defineStore('settings', () => {
])
const [health, status, index, policy] = results
aiCoreStatus.value = health.status === 'fulfilled' && health.value.status === 'ok' ? 'running' : 'error'
aiCoreVersion.value = status.status === 'fulfilled' ? status.value.version : '未获取'
aiCoreVersion.value = status.status === 'fulfilled' ? status.value.version : ''
indexStatus.value = index.status === 'fulfilled' ? index.value : emptyIndex()
permissionPolicy.value = policy.status === 'fulfilled' ? policy.value : {}
diagnosticsError.value = results.filter(item => item.status === 'rejected').map(item => item.reason instanceof Error ? item.reason.message : '后端请求失败').join('') || null
diagnosticsError.value = results.filter(item => item.status === 'rejected').map(item => item.reason instanceof Error ? item.reason.message : t('后端请求失败', 'Backend request failed')).join(t('', '; ')) || null
}
function setAutoSaveInterval(ms: number) {
@@ -69,7 +69,7 @@ export const useSettingsStore = defineStore('settings', () => {
indexStatus.value = await indexService.getIndexStatus()
} catch (reason) {
indexStatus.value.status = 'error'
indexStatus.value.error = reason instanceof Error ? reason.message : '索引重建失败'
indexStatus.value.error = reason instanceof Error ? reason.message : t('索引重建失败', 'Index rebuild failed')
}
}
+2 -1
View File
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { Skill } from '@/contracts'
import * as skillService from '@/services/skillService'
import { t } from '@/i18n'
export const useSkillStore = defineStore('skill', () => {
const skills = ref<Skill[]>([])
@@ -23,7 +24,7 @@ export const useSkillStore = defineStore('skill', () => {
skills.value = await skillService.listSkills()
error.value = null
} catch (reason) {
error.value = reason instanceof Error ? reason.message : 'Skill 加载失败'
error.value = reason instanceof Error ? reason.message : t('Skill 加载失败', 'Failed to load Skills')
} finally {
isLoading.value = false
}
+2 -1
View File
@@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { TaskItem, TaskStatus, TaskPriority, TaskSource } from '@/contracts'
import { createTask as createTaskRequest, deleteTask as deleteTaskRequest, listTasks, updateTask as updateTaskRequest } from '@/services/taskService'
import { t } from '@/i18n'
export const useTaskStore = defineStore('task', () => {
const tasks = ref<TaskItem[]>([])
@@ -31,7 +32,7 @@ export const useTaskStore = defineStore('task', () => {
tasks.value = resp.items
error.value = null
} catch (reason) {
error.value = reason instanceof Error ? reason.message : '任务加载失败'
error.value = reason instanceof Error ? reason.message : t('任务加载失败', 'Failed to load tasks')
} finally {
isLoading.value = false
}