open-notebook/frontend/src/lib/locales/zh-CN/index.ts
Luis Novo 3f352cfcce
feat: credential-based API key management (#477) (#540)
* feat: replace provider config with credential-based system (#477)

Introduce a new credential management system replacing the old
ProviderConfig singleton and standalone Models page. Each credential
stores encrypted API keys and provider-specific configuration with
full CRUD support via a unified settings UI.

Backend:
- Add Credential domain model with encrypted API key storage
- Add credentials API router (CRUD, discovery, registration, testing)
- Add encryption utilities for secure key storage
- Add key_provider for DB-first env-var fallback provisioning
- Add connection tester and model discovery services
- Integrate ModelManager with credential-based config
- Add provider name normalization for Esperanto compatibility
- Add database migrations 11-12 for credential schema

Frontend:
- Rewrite settings/api-keys page with credential management UI
- Add model discovery dialog with search and custom model support
- Add compact default model assignments (primary/advanced layout)
- Add inline model testing and credential connection testing
- Add env-var migration banner
- Update navigation to unified settings page
- Remove standalone models page and old settings components

i18n:
- Update all 7 locale files with credential and model management keys

Closes #477

Co-Authored-By: JFMD <git@jfmd.us>
Co-Authored-By: OraCatQAQ <570768706@qq.com>

* fix: address PR #540 review comments

- Fix docs referencing removed Models page
- Fix error-handler returning raw messages instead of i18n keys
- Fix auth.py misleading docstring and missing no-password guard
- Fix connection_tester using wrong env var for openai_compatible
- Add provision_provider_keys before model discovery/sync
- Update CLAUDE.md to reflect credential-based system
- Fix missing closing brace in api-keys page useEffect

* fix: add logging to credential migration and surface errors in UI

- Add comprehensive logging to migrate-from-env and
  migrate-from-provider-config endpoints (start, per-provider
  progress, success/failure with stack traces, final summary)
- Fix frontend migration hooks ignoring errors array from response
- Show error toast when migration fails instead of "nothing to migrate"
- Invalidate status/envStatus queries after migration so banner updates

* docs: update CLAUDE.md files for credential system

Replace stale ProviderConfig and /api-keys/ references across 8 CLAUDE.md
files to reflect the new Credential-based system from PR #540.

* docs: update user documentation for credential-based system

Replace env var API key instructions with Settings UI credential
workflow across all user-facing documentation. The new flow is:
set OPEN_NOTEBOOK_ENCRYPTION_KEY → start services → add credential
in Settings UI → test → discover models → register.

- Rewrite ai-providers.md, api-configuration.md, environment-reference.md
- Update all quick-start guides and installation docs
- Update ollama.md, openai-compatible.md, local-tts/stt networking sections
- Update reverse-proxy.md, development-setup.md, security.md
- Fix broken links to non-existent docs/deployment/ paths
- Add credentials endpoints to api-reference.md
- Move all API key env vars to deprecated/legacy sections

* chore: bump version to 1.7.0-rc1

Release candidate for credential-based provider management system.

* fix: initialize provider before try block in test_credential

Prevents UnboundLocalError when Credential.get() throws (e.g.,
invalid credential_id) before provider is assigned.

* fix: reorder down migration to drop index before table

Removes duplicate REMOVE FIELD statement and reorders so the index
is dropped before the table, preventing rollback failures.

* refactor: simplify encryption key to always derive via SHA-256

Remove the dual code path in _ensure_fernet_key() that detected native
Fernet keys. Since the credential system is new, always deriving via
SHA-256 removes unnecessary complexity. Also removes the generate_key()
function and Fernet.generate_key() references from docs.

* fix: correct mock patch targets in embedding tests and URL validation

Fix embedding tests patching wrong module path for model_manager
(was targeting open_notebook.utils.embedding.model_manager but it's
imported locally from open_notebook.ai.models). Also fix URL validation
to allow unresolvable hostnames since they may be valid in the
deployment environment (e.g., Azure endpoints, internal DNS).

* feat: add global setup banner for encryption and migration status

Show a persistent banner in AppShell when encryption key is missing
(red) or env var API keys can be migrated (amber), so users see
these prompts on every page instead of only on Settings > API Keys.

Includes a docs link for the encryption banner and i18n support
across all 7 locales.

* docs: several improvements to docker-compose e env examples

* Update README.md

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

* docs: fix env var format in README and update model setup instructions

Align the encryption key snippet in README Step 2 with the list
format used in the compose file. Replace deprecated "Settings →
Models" instructions with credential-based Discover Models flow.

* fix: address credential system review issues

- Fix SSRF bypass via IPv4-mapped IPv6 addresses (::ffff:169.254.x.x)
- Fix TTS connection test missing config parameter
- Add Azure-specific model discovery using api-key auth header
- Add Vertex static model list for credential-based discovery
- Fix PROVIDER_DISCOVERY_FUNCTIONS incorrect azure/vertex mapping
- Extract business logic to api/credentials_service.py (service layer)
- Move credential Pydantic schemas to api/models.py
- Update tests to use new service imports and ValueError assertions

* fix: sanitize error responses and migrate key_provider to Credential

- Replace raw exception messages in all credential router 500 responses
  with generic error strings (internal details logged server-side only)
- Refactor key_provider.py to use Credential.get_by_provider() instead
  of deprecated ProviderConfig.get_instance()
- Remove unused functions (get_provider_configs, get_default_api_key,
  get_provider_config) that were dead code

---------

Co-authored-by: JFMD <git@jfmd.us>
Co-authored-by: OraCatQAQ <570768706@qq.com>
2026-02-10 08:30:22 -03:00

1067 lines
48 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export const zhCN = {
common: {
search: "搜索...",
chat: '聊天',
notes: '笔记',
create: "新建",
new: "新建",
cancel: "取消",
save: "保存",
nameRequired: "这是必填项",
delete: "删除",
edit: "编辑",
actions: "快捷操作",
theme: "主题",
signOut: "退出登录",
noMatches: "未找到匹配项",
tryDifferentSearch: "尝试使用不同的搜索词。",
light: "浅色",
dark: "深色",
system: "系统",
loading: "加载中...",
note: "笔记",
insight: "洞察",
newSource: "新建来源",
newNotebook: "新建笔记本",
newPodcast: "新建播客",
language: "语言",
english: "English",
chinese: "简体中文",
japanese: "日本語",
russian: "Русский",
source: "来源",
notebook: "笔记本",
podcast: "播客",
quickActions: "快捷操作",
quickActionsDesc: "导航、搜索、提问、主题",
appName: "Open Notebook",
add: "添加",
remove: "移除",
confirm: "确认",
warning: "警告",
error: "操作失败",
success: "操作成功",
modelConfiguration: "模型配置",
resetToDefault: "重置为默认",
sessions: "会话",
model: "模型",
send: "发送",
back: "返回",
next: "下一步",
done: "完成",
processing: "处理中...",
creating: "创建中...",
tokenCount: "Token",
charCount: "字符",
linked: "已关联",
added: "已于 {date} 添加",
adding: "正在添加...",
addSelected: "添加所选",
customModel: "自定义模型",
messages: "消息",
failed: "失败",
current: "当前",
writeNote: '撰写笔记',
batchMode: "批量模式",
optional: "可选",
type: "类型",
title: "标题",
created: "创建于 {time}",
updated: "更新于 {time}",
noResults: "未找到结果",
references: "引用",
refreshPage: "请重试刷新页面",
refresh: "刷新",
aiGenerated: "AI 生成",
human: "人类",
unknown: "未知",
details: "详情",
deleteForever: "永久删除",
connectionError: "连接错误",
unableToConnect: "无法连接到 API 服务器",
retryConnection: "重试连接",
diagnosticInfo: "诊断信息",
version: "版本",
built: "构建时间",
apiUrl: "API 地址",
frontendUrl: "前端地址",
checkConsoleLogs: "请检查浏览器控制台获取详细日志(搜索 🔧 [Config] 消息)",
yes: "是",
no: "否",
simple: "简单",
saving: "正在保存...",
description: "描述",
saveToNote: "保存到笔记",
copyToClipboard: "复制到剪贴板",
close: "关闭",
insights: "见解",
progress: "进度",
deleting: "正在删除...",
created_label: "创建时间",
updated_label: "更新时间",
download: "下载",
saveChanges: "保存更改",
name: "名称",
default: "默认",
notFound: "未找到",
reasoning: "推理过程",
searchTerms: "搜索词",
strategy: "策略",
individualAnswers: "独立回答 ({count})",
finalAnswer: "最终回答",
notebookLabel: "笔记本: {name}",
itemNotFound: "未找到该 {type}",
accessibility: {
navigation: "导航",
transformationViews: "转换视图",
searchKB: "向知识库提问或搜索",
searchNotebooks: "搜索笔记本",
enterQuestion: "输入您的问题以询问知识库",
enterSearch: "输入搜索词",
searchKBBtn: "搜索知识库",
podcastViews: "播客视图",
chatSessions: "对话 Session",
ytVideo: "YouTube 视频",
askResponse: "提问回答",
},
url: "URL",
errorDetails: "错误详情",
editTransformation: "编辑转换规则",
comingSoon: "敬请期待",
retry: "重试",
traditionalChinese: "繁体中文",
portuguese: "葡萄牙语",
completed: "已完成",
saveSuccess: "保存成功",
contextModes: {
off: "未包含在聊天中",
insights: "仅限见解",
full: "全部内容",
clickToCycle: "点击循环切换",
},
clickToEdit: "点击编辑",
},
apiErrors: {
notebookNotFound: "找不到笔记本",
sourceNotFound: "找不到源文件",
transformationNotFound: "找不到转换规则",
fileUploadFailed: "文件上传失败",
urlRequired: "链接类型需要提供 URL",
contentRequired: "文本类型需要提供内容",
invalidSourceType: "无效的源类型",
processingFailed: "处理失败",
failedToQueue: "排队处理失败",
invalidSortBy: "排序字段必须是 'created' 或 'updated'",
invalidSortOrder: "排序方向必须是 'asc' 或 'desc'",
accessDenied: "文件访问被拒绝",
fileNotFoundOnServer: "服务器上找不到该文件",
failedToCreateSession: "创建对话失败",
failedToUpdateSession: "更新会话失败",
failedToDeleteSession: "删除会话失败",
failedToSendMessage: "发送消息失败",
pleaseEnterQuestion: "请输入问题",
pleaseConfigureModels: "请配置所有必选模型",
askFailed: "提问失败",
searchFailed: "搜索失败",
unauthorized: "无权访问,请检查您的密码",
invalidPassword: "密码错误",
missingAuth: "缺少身份验证信息",
embeddingModelRequired: "此功能需要嵌入模型。请在模型设置中配置一个。",
strategyModelNotFound: "未找到策略模型",
answerModelNotFound: "未找到回答模型",
finalAnswerModelNotFound: "未找到最终回答模型",
noAnswerGenerated: "未能生成回答",
genericError: "发生了意外错误",
},
connectionErrors: {
apiTitle: "无法连接到 API 服务器",
apiDesc: "无法访问 Open Notebook API 服务器",
dbTitle: "数据库连接失败",
dbDesc: "API 服务器正在运行,但无法访问数据库",
troubleshooting: "这通常意味着:",
apiUnreachable1: "API 服务器未运行",
apiUnreachable2: "API 服务器运行在不同的地址",
apiUnreachable3: "网络连接问题",
dbFailed1: "SurrealDB 未运行",
dbFailed2: "数据库连接设置不正确",
dbFailed3: "API 与数据库之间的网络问题",
quickFixes: "快速修复:",
setApiUrl: "设置 API_URL 环境变量:",
checkSurreal: "检查 SurrealDB 是否运行:",
seeDocumentation: "有关详细设置说明,请参阅:",
docLink: "Open Notebook 文档",
showTechnical: "显示技术细节",
attemptedUrl: "尝试的 URL",
message: "消息",
technicalDetails: "技术细节",
stackTrace: "堆栈跟踪",
retryLabel: "重试连接",
retryHint: "按 R 或点击按钮重试",
dockerLabel: "对于 Docker",
localDevLabel: "对于本地开发",
},
auth: {
loginTitle: "Open Notebook",
loginDesc: "输入密码以访问应用程序",
passwordPlaceholder: "密码",
signingIn: "正在登录...",
signIn: "登录",
unhandledError: "登录过程中出现未处理的错误",
connectErrorHint: "无法连接到服务器。请检查 API 是否正在运行。",
},
navigation: {
collect: "采集",
process: "处理",
create: "创作",
manage: "管理",
sources: "来源",
notebooks: "笔记本",
askAndSearch: "询问与搜索",
search: "搜索",
ask: "提问",
podcasts: "播客",
models: "模型",
transformations: "转换",
transformation: "转换",
settings: "设置",
advanced: "高级",
nav: "导航",
language: "切换语言",
theme: "主题",
},
notebooks: {
title: "笔记本",
newNotebook: "创建笔记本",
searchPlaceholder: "搜索笔记本...",
archived: "已归档",
archive: "归档",
unarchive: "取消归档",
deleteNotebook: "删除笔记本",
deleteNotebookDesc: "您确定要删除 \"{name}\" 吗?此操作无法撤销。",
deleteNotebookLoading: "正在加载删除预览...",
deleteNotebookNotes: "{count} 个笔记将被永久删除。",
deleteNotebookNoNotes: "没有要删除的笔记。",
deleteNotebookExclusiveSources: "{count} 个来源仅存在于此笔记本中。",
deleteNotebookSharedSources: "{count} 个来源与其他笔记本共享,将被取消关联。",
deleteNotebookNoSources: "此笔记本中没有来源。",
deleteExclusiveSourcesLabel: "删除专属来源",
keepExclusiveSourcesLabel: "取消关联并保留",
activeNotebooks: "活动的笔记本",
archivedNotebooks: "归档的笔记本",
emptyDescription: "从创建您的第一个笔记本开始,组织您的研究。",
noActiveNotebooks: "没有活动的笔记本",
noArchivedNotebooks: "没有归档的笔记本",
notFound: "未找到笔记本",
notFoundDesc: "请求的笔记本不存在。",
noDescription: "暂无描述...",
updated: "已更新",
namePlaceholder: "笔记本名称",
addDescription: "添加描述...",
noNotesYet: "暂无笔记",
deleteNote: "删除笔记",
deleteNoteConfirm: "确定要删除此笔记吗?此操作无法撤销。",
noteCreatedSuccess: "笔记创建成功",
failedToCreateNote: "创建笔记失败",
noteUpdatedSuccess: "笔记更新成功",
failedToUpdateNote: "更新笔记失败",
noteDeletedSuccess: "笔记删除成功",
failedToDeleteNote: "删除笔记失败",
createNew: "创建新笔记本",
createNewDesc: "输入名称和可选描述以开始。",
descPlaceholder: "在此添加有关此笔记本的更多信息...",
createSuccess: "笔记本创建成功",
updateSuccess: "笔记本更新成功",
deleteSuccess: "笔记本删除成功",
},
sources: {
title: "来源",
add: "添加来源",
addNew: "添加新来源",
addExisting: "添加现有来源",
allSourcesDescShort: "在此查看所有来源。",
cannotSaveNoteNoNotebook: "无法保存笔记:缺少笔记本 ID",
empty: "暂无来源",
emptyDesc: "添加您的第一个来源,开始构建您的知识库。",
delete: "删除来源",
deleteMsg: "确定要删除此来源吗?此操作无法撤销。",
statusPreparing: "正在准备",
statusQueued: "已排队",
statusProcessing: "正在处理",
statusCompleted: "已完成",
statusFailed: "处理失败",
statusPreparingDesc: "准备处理中",
statusQueuedDesc: "等待处理",
statusProcessingDesc: "正在处理内容",
statusCompletedDesc: "处理成功",
statusFailedDesc: "处理失败",
failedToLoad: "加载来源失败",
allSourcesDesc: "在此查看所有来源。您可以添加新来源或管理现有来源。",
allSources: "所有来源",
insights: "见解",
yes: "是",
no: "否",
loadingMore: "正在加载更多...",
deleteConfirm: "确定要删除吗?",
deleteConfirmWithTitle: "确定要删除 \"{title}\" 吗?",
deleteSuccess: "来源删除成功。注意:要从存储中删除文件,必须在设置页面中启用“删除文件”选项。",
failedToDelete: "删除来源失败",
sourceQueued: "来源已加入队列",
sourceQueuedDesc: "来源已提交进行后台处理。您可以在来源列表中监控进度。",
sourceAddedSuccess: "来源添加成功",
failedToAddSource: "添加来源失败",
sourceUpdatedSuccess: "来源更新成功",
failedToUpdateSource: "更新来源失败",
sourceDeletedSuccess: "来源删除成功",
failedToDeleteSource: "删除来源失败",
fileUploadedSuccess: "文件上传成功",
failedToUploadFile: "文件上传失败",
sourceRequeued: "来源重试已加入队列",
sourceRequeuedDesc: "来源已重新加入处理队列。",
failedToRetry: "重试失败",
failedToRetryDesc: "重试来源处理失败。请重试。",
sourcesAddedToNotebook: "{count} 个来源已添加到笔记本",
failedToAddSourcesToNotebook: "添加来源到笔记本失败",
partialAddSuccess: "{success} 个来源已添加,{failed} 个失败",
sourceRemovedFromNotebook: "来源已成功从笔记本中移除",
failedToRemoveSourceFromNotebook: "从笔记本中移除来源失败",
removeConfirm: "确定要从此笔记本移除吗?",
noSourcesYet: "暂无来源",
createFirstSource: "添加您的第一个来源开始构建知识库。",
deleteSourceConfirm: "确定要删除此来源吗?",
checking: "正在检查...",
untitledSource: "未命名来源",
maxItems: "最多 {count} 个",
insightsCount: "{count} 条见解",
details: "详情",
detailsTitle: "来源详情",
content: "内容",
metadata: "元数据",
type: {
link: "链接",
file: "文件",
text: "文本",
},
id: "来源 ID",
topics: "主题",
embedded: "已嵌入向量",
notEmbedded: "未嵌入向量",
embedContent: "嵌入内容",
embedding: "正在嵌入...",
alreadyEmbedded: "已嵌入",
downloadFile: "下载文件",
fileUnavailable: "文件不可用",
preparing: "正在准备...",
generateNewInsight: "生成新见解",
selectTransformation: "选择转换规则...",
noInsightsYet: "暂无见解",
createFirstInsight: "使用上方的转换规则创建您的第一个见解",
viewInsight: "查看见解",
viewSource: "查看来源",
noInsightSelected: "未选择见解",
sourceInsight: "来源见解",
manageNotebooks: "管理所属笔记本",
manageNotebooksDesc: "管理包含此来源的笔记本",
noNotebooksAvailable: "暂无可用笔记本",
deleteInsight: "删除见解",
deleteInsightConfirm: "确定要删除此见解吗?此操作无法撤销。",
insightGenerationStarted: "见解生成已开始,稍后将显示。",
notEmbeddedAlert: "内容未嵌入向量",
notEmbeddedDesc: "此内容尚未为了向量搜索进行嵌入。嵌入可以启用高级搜索功能并更好地发现内容。",
openOnYoutube: "在 YouTube 上打开",
urlCopied: "URL 已复制到剪贴板",
loadFailed: "加载来源详情失败",
removeFromNotebook: "从笔记本移除",
retryProcessing: "重试处理",
deleteSource: "删除来源",
retry: "重试",
progress: "进度",
addExistingTitle: "添加现有来源",
addExistingDesc: "从您的所有笔记本中选择已有的来源添加到当前笔记本。",
searchPlaceholder: "通过名称或 URL 搜索来源...",
noNotebooksFound: "未找到笔记本。",
showingFirst100: "仅显示前 100 个来源。请使用搜索功能查找特定来源。",
selectedCount: "已选择 {count} 个来源",
added: "已添加于 {date}",
noNotesYet: '暂无笔记',
createFirstNote: '创建您的第一条笔记,记录见解与观察。',
deleteNote: '删除笔记',
deleteNoteConfirm: '您确定要删除此笔记吗?此操作无法撤销。',
editNote: '编辑笔记',
createNote: '创建笔记',
addTitle: '添加标题...',
untitledNote: '无标题笔记',
writeNotePlaceholder: '在此处编写您的笔记内容...',
saveNote: '保存笔记',
createNoteBtn: '创建笔记',
urlLabel: 'URL(s) *',
fileLabel: '文件(s) *',
textContentLabel: '文本内容 *',
enterUrlsPlaceholder: '每行输入一个 URL\nhttps://example.com/article1\nhttps://example.com/article2',
batchUrlHint: '粘贴多个 URL每行一个进行批量导入',
invalidUrlsDetected: '检测到无效的 URL',
lineLabel: '第 {line} 行',
fixInvalidUrls: '请修正或移除无效的 URL 以继续',
selectMultipleFilesHint: '选择多个文件进行批量导入。支持:文档 (PDF, DOC, DOCX, PPT, XLS, EPUB, TXT, MD),媒体 (MP4, MP3, WAV, M4A),图片 (JPG, PNG),归档 (ZIP)',
selectedFiles: '已选择文件:',
textPlaceholder: '在此处粘贴或输入您的内容...',
htmlDetected: '检测到 HTML 内容。处理后将转换为 Markdown。',
titlePlaceholder: '为您的来源起一个描述性的标题',
batchTitlesAuto: '将为每个来源自动生成标题。',
batchCommonSettings: '同样的笔记本和转换将应用于所有项目。',
urlsCount: '{count} 个 URL',
filesCount: '{count} 个文件',
addSource: "添加来源",
addUrl: "添加 URL",
uploadFile: "上传文件",
enterText: "输入文本",
processDescription: "内容将经过处理并由 AI 分析。",
processingFiles: "正在处理您的文件...",
titleRequired: "文本内容必须提供标题",
titleGenerated: "如果留空,将根据内容自动生成标题",
batchCount: "将处理 {count} 个{type}",
enableEmbedding: "启用搜索向量嵌入",
embeddingDesc: "允许此来源在向量搜索和 AI 查询中被检索",
embeddingAlways: "已自动启用嵌入",
embeddingAlwaysDesc: "您的设置已配置为始终对内容进行向量嵌入。",
embeddingNever: "嵌入已禁用",
embeddingNeverDesc: "您的设置已配置为跳过嵌入。此来源将无法进行向量搜索。",
changeInSettings: "您可以在此处更改设置:",
notFound: "未找到来源",
noContent: "暂无内容",
insightsDesc: "根据模型分析生成的见解",
uploadedFile: "已上传文件",
fileUnavailableDesc: "由于存储系统原因,此文件目前不可用。",
batchSuccess: "成功创建 {count} 个来源",
batchFailed: "全部 {count} 个来源创建失败",
batchPartial: "{success} 个成功,{failed} 个失败",
submittingSource: "正在提交来源进行处理...",
contentRequired: "请提供所选来源类型所需的内容",
titleRequiredForText: "文本来源需要提供标题",
processingBatchSources: "正在处理 {count} 个来源,请稍候...",
processingSource: "正在处理您的来源,请稍候...",
maxFilesAllowed: "每批最多允许 {count} 个文件",
},
chat: {
sessions: "会话",
sessionTitlePlaceholder: "在此输入标题...",
noSessions: "暂无会话",
startChatting: "开始针对您的来源进行聊天。",
deleteSession: "删除会话",
deleteSessionDesc: "确定要删除此聊天会话吗?此操作无法撤销。",
sendPlaceholder: "向您的来源提问...",
newChat: "新建对话",
sessionsTitle: "对话列表",
clearhistory: "清空历史",
renameSession: "重命名会话",
noSourcesLinked: "未关联来源",
thinking: "AI 正在思考...",
chatWith: "与{name}对话",
startConversation: "开始针对{type}进行对话",
askQuestions: "提出问题以更好地理解内容",
pressToSend: "按 {key} 发送",
model: "模型",
createToStart: '创建一个会话以开始。',
chatWithNotebook: '与笔记本对话',
unableToLoadChat: '无法加载聊天',
noDescription: '暂无描述',
startByCreating: '从创建您的第一个笔记本开始,组织您的研究。',
messagesCount: "{count} 条消息",
sessionCreated: "聊天会话已创建",
sessionUpdated: "会话已更新",
sessionDeleted: "会话已删除",
},
searchPage: {
askAndSearch: "提问与搜索",
chooseAMode: "选择模式",
askBeta: "提问 (beta)",
search: "搜索",
askYourKb: "向您的知识库提问 (beta)",
askYourKbDesc: "大语言模型将根据您知识库中的文档回答您的查询。",
question: "问题",
enterQuestionPlaceholder: "输入您的问题...",
pressToSubmit: "按 Cmd/Ctrl+Enter 提交",
noEmbeddingModel: "您无法使用此功能,因为尚未选择嵌入模型。请在模型页面设置一个。",
usingCustomModels: "正在使用自定义模型",
usingDefaultModels: "正在使用默认模型",
advanced: "高级",
strategy: "策略",
answer: "回答",
final: "最终",
ask: "提问",
processing: "处理中...",
saveToNotebooks: "保存到笔记本",
searchDesc: "在您的知识库中搜索特定的关键字或概念",
enterSearchPlaceholder: "输入搜索查询...",
pressToSearch: "按 Enter 键搜索",
searchType: "搜索类型",
vectorSearchWarning: "向量搜索需要嵌入模型。目前仅文本搜索可用。",
textSearch: "文本搜索",
vectorSearch: "向量搜索",
searchIn: "搜索范围",
searchSources: "搜索来源",
searchNotes: "搜索笔记",
resultsFound: "{count} 个结果",
matches: "匹配项 ({count})",
noResultsFor: "未找到 “{query}” 的结果",
notSet: "未设置",
saveToNotebook: "保存到笔记本",
saveSuccess: "成功保存到笔记本",
saveError: "保存到笔记本失败",
selectNotebook: "选择笔记本",
createNewNotebook: "创建新笔记本",
cancel: "取消",
saving: "保存中...",
advancedModelTitle: "高级模型选择",
advancedModelDesc: "为提问过程的每个阶段选择特定的模型",
strategyModel: "策略模型",
answerModel: "回答模型",
finalAnswerModel: "最终回答模型",
selectStrategyPlaceholder: "选择策略模型",
selectAnswerPlaceholder: "选择回答模型",
selectFinalPlaceholder: "选择最终回答模型",
saveChanges: "保存更改",
searchAndAsk: "搜索与提问",
searchResultsFor: "搜索 “{query}”",
askAbout: "提问关于 “{query}”",
orSearchKb: "或搜索您的知识库",
processingQuestion: "正在处理您的问题...",
},
podcasts: {
generateEpisode: "生成播客单集",
generateEpisodeDesc: "在生成新的播客单集之前,选择要包含的内容并配置单集详情。",
content: "内容",
contentDesc: "选择要包含在此单集中的笔记本、来源和笔记。",
itemsSelected: "{count} 个项目已选择",
tokens: "{count} token",
chars: "{count} 字符",
loadingNotebooks: "正在加载笔记本...",
noNotebooksFoundInPodcasts: "未找到笔记本。在生成播客之前,请先创建一个笔记本并添加内容。",
noContentSelected: "未选择内容",
summary: "摘要",
fullContent: "全部内容",
untitledSource: "未命名来源",
untitledNote: "未命名笔记",
episodeSettings: "单集设置",
episodeProfile: "单集简介",
episodeProfilePlaceholder: "选择单集简介",
episodeName: "单集名称",
episodeNamePlaceholder: "例如AI 与工作的未来",
additionalInstructions: "附加指令",
instructionsPlaceholder: "任何要追加到单集简讯的补充建议...",
generating: "正在生成...",
generate: "生成",
hostPlaceholder: "主持人 {number}",
profileRequired: "需要单集简介",
profileRequiredDesc: "在生成播客之前,请选择一个单集简介。",
nameRequired: "需要单集名称",
nameRequiredDesc: "请为单集提供一个名称。",
addContext: "添加上下文",
addContextDesc: "至少选择一个来源或笔记包含在单集中。",
generationFailed: "播客生成失败",
speakerProfile: "主持人简介",
usesSpeakerProfile: "使用主持人简介",
sources: "来源",
notes: "笔记",
noSources: "此笔记本中没有可用的来源。",
noNotes: "此笔记本中没有可用的笔记。",
selectMode: "选择模式",
buildContextFailed: "构建上下文失败。请检查您的选择。",
podcastTaskStarted: "播客生成任务已开始",
loadingProfiles: "正在加载单集简介...",
noProfilesFound: "未找到单集简介。在生成播客之前,请先创建一个单集简介。",
listTitle: "播客",
listDesc: "跟踪生成的单集并管理可重复使用的模板。",
chooseAView: "选择视图",
episodesTab: "单集",
templatesTab: "模板",
overviewTitle: "单集概览",
overviewDesc: "监控播客生成任务并查看最终成品。",
generateBtn: "生成播客",
total: "总计",
processingLabel: "处理中",
completedLabel: "已完成",
failedLabel: "失败",
pendingLabel: "排队中",
loadErrorTitle: "加载单集失败",
loadErrorDesc: "无法获取最新的播客单集。请稍后重试。",
loadingEpisodes: "正在加载单集...",
noEpisodesYet: "暂无播客单集。从笔记本或来源聊天界面开始生成您的第一个单集。",
statusRunningTitle: "正在处理中",
statusRunningDesc: "正在活跃生成资产的单集。",
statusPendingTitle: "排队中 / 待处理",
statusPendingDesc: "已提交并在等待开始处理的单集。",
statusCompletedTitle: "已完成单集",
statusCompletedDesc: "可以查看、下载或发布。",
statusFailedTitle: "失败单集",
statusFailedDesc: "在生成过程中遇到问题的单集。",
templatesWorkspaceTitle: "模板工作区",
templatesWorkspaceDesc: "构建可重复使用的单集和发言人配置,以实现快速的播客制作。",
howTemplatesPowerTitle: "模板如何驱动播客生成",
howTemplatesPowerDesc: "模板将播客工作流拆分为两个可重复使用的构建块。在生成新单集时可以随时混合搭配它们。",
episodeProfilesSetFormat: "单集简介设定格式",
episodeProfilesList1: "概述分段数量及故事流向",
episodeProfilesList2: "选择用于简报、大纲和脚本编写的语言模型",
episodeProfilesList3: "存储默认简报,以便每个单集都以一致的基调开始",
speakerProfilesBringVoices: "发言人简介赋予声音生命",
speakerProfilesList1: "选择文字转语音库及模型",
speakerProfilesList2: "记录每个发言人的性格、背景故事和发音说明",
speakerProfilesList3: "在不同的单集格式中重复使用相同的主持人或嘉宾声音",
recommendedWorkflow: "推荐工作流",
workflowStep1: "为您需要的每个声音创建发言人简介",
workflowStep2: "构建按名称引用这些发言人的单集简介",
workflowStep3: "通过选择适合故事的单集简介来生成播客",
workflowHint: "单集简介按名称引用发言人简介,因此从发言人开始可以避免以后缺少声音指派。",
failedToLoadTemplates: "加载模板数据失败",
failedToLoadTemplatesDesc: "请确保 API 正在运行并重试。某些部分可能不完整。",
loadingTemplates: "正在加载模板...",
speakerProfilesTitle: "发言人简介",
speakerProfilesDesc: "为生成的单集配置声音和性格。",
createSpeaker: "创建发言人",
noSpeakerProfiles: "暂无发言人简介。创建一个以使单集模板可用。",
noDescription: "未提供描述。",
usedByCount_one: "被 1 个单集使用",
usedByCount_other: "被 {count} 个单集使用",
usedByCount: "被 {count} 个单集使用",
unused: "未使用",
voiceId: "声音 ID",
backstory: "背景故事",
personality: "性格",
edit: "编辑",
duplicate: "复制",
deleteSpeakerProfileTitle: "删除发言人简介?",
deleteSpeakerProfileDesc: "删除 “{name}” 无法撤销。",
deleteSpeakerDisabledHint: "在删除之前,请先从单集简介中移除该发言人。",
deleting: "正在删除...",
episodeProfilesTitle: "单集简介",
episodeProfilesDesc: "为您播客定义可重复使用的生成设置。",
createProfile: "创建简介",
createSpeakerFirst: "在添加单集简介之前,请先创建一个发言人简介。",
noEpisodeProfiles: "暂无单集简介。创建一个以启动播客生成。",
deleteProfileTitle: "删除简介?",
deleteProfileDesc: "这将移除 “{name}”。现有单集将保留其数据,但新单集将不再使用此配置。",
outlineModel: "大纲模型",
transcriptModel: "脚本模型",
segments: "分段数量",
defaultBriefingTitle: "默认简报",
created: "创建于 {time}",
details: "详情",
summaryTab: "总结",
outlineTab: "大纲",
transcriptTab: "脚本",
briefing: "内容简报",
noOutline: "暂无大纲。",
noTranscript: "暂无脚本。",
deleteEpisodeTitle: "删除单集?",
deleteEpisodeDesc: "这将永久移除 “{name}” 及其音频文件。",
audioUnavailable: "音频不可用",
segment: "分段",
speaker: "发言人",
profile: "简介",
link: "链接",
file: "文件",
embedded: "已嵌入",
notEmbedded: "未嵌入",
noSpeakerProfilesAvailable: "没有可用的发言人简介",
noLanguageModelsAvailable: "没有可用的语言模型",
editEpisodeProfile: "编辑单集简介",
createEpisodeProfile: "创建单集简介",
episodeProfileFormDesc: "定义单集生成的规则及默认使用的发言人配置。",
noSpeakerProfilesDesc: "在配置单集简介之前,请先创建一个发言人简介。",
noLanguageModelsDesc: "在“模型”部分添加语言模型,以配置大纲和文稿生成。",
profileName: "简介名称",
profileNamePlaceholder: "例如:技术讨论",
descriptionPlaceholder: "简要说明何时使用此简介",
speakerConfig: "发言人配置",
selectSpeakerProfile: "选择发言人简介",
outlineGeneration: "大纲生成",
transcriptGeneration: "文稿生成",
defaultBriefingPlaceholder: "概述此单集格式的结构、语气和目标",
editSpeakerProfile: "编辑发言人简介",
createSpeakerProfile: "创建发言人简介",
speakerProfileFormDesc: "配置文字转语音设置并定义最多四名发言人。",
noTtsModelsAvailable: "没有可用的文字转语音模型",
noTtsModelsDesc: "在创建发言人简介之前,请先在“模型”部分添加 TTS 模型。",
speakers: "发言人",
speakersDesc: "为此简介配置一到四种声音。",
addSpeaker: "添加发言人",
speakerNumber: "发言人 {number}",
backstoryPlaceholder: "发言人的简要传记或背景信息",
personalityPlaceholder: "描述风格和语气",
outlineProviderRequired: "必须选择大纲提供商",
outlineModelRequired: "必须选择大纲模型",
transcriptProviderRequired: "必须选择文稿提供商",
transcriptModelRequired: "必须选择文稿模型",
defaultBriefingRequired: "必须填写默认简介",
segmentsInteger: "必须是整数",
segmentsMin: "至少包含 3 个分段",
segmentsMax: "最多包含 20 个分段",
voiceIdRequired: "必须填写声音 ID",
backstoryRequired: "必须填写背景故事",
personalityRequired: "必须填写性格描述",
speakerCountMin: "至少需要一个发言人",
speakerCountMax: "最多只能配置 4 个发言人",
delete: "删除",
unknown: "未知",
deleteSuccess: "播客删除成功",
failedToDelete: "删除播客失败",
episodeDeleted: "剧集已删除",
episodeDeletedDesc: "播客剧集已成功移除。",
failedToDeleteEpisode: "删除剧集失败",
profileCreated: "剧集配置已创建",
profileCreatedDesc: "新的剧集配置已准备就绪。",
failedToCreateProfile: "创建剧集配置失败",
profileUpdated: "剧集配置已更新",
profileUpdatedDesc: "更改已成功保存。",
failedToUpdateProfile: "更新剧集配置失败",
profileDeleted: "剧集配置已删除",
profileDeletedDesc: "配置已成功移除。",
failedToDeleteProfile: "删除剧集配置失败",
failedToDeleteProfileDesc: "请确保配置未在使用中并重试。",
profileDuplicated: "剧集配置已复制",
profileDuplicatedDesc: "已创建配置副本。",
failedToDuplicateProfile: "复制剧集配置失败",
speakerCreated: "发言人配置已创建",
speakerCreatedDesc: "发言人配置已准备就绪。",
failedToCreateSpeaker: "创建发言人配置失败",
speakerUpdated: "发言人配置已更新",
speakerUpdatedDesc: "更改已成功保存。",
failedToUpdateSpeaker: "更新发言人配置失败",
speakerDeleted: "发言人配置已删除",
speakerDeletedDesc: "配置已成功移除。",
failedToDeleteSpeaker: "删除发言人配置失败",
failedToDeleteSpeakerDesc: "请确保配置未在使用中并重试。",
speakerDuplicated: "发言人配置已复制",
speakerDuplicatedDesc: "已创建配置副本。",
failedToDuplicateSpeaker: "复制发言人配置失败",
generationStarted: "播客启动生成",
generationStartedDesc: "剧集 \"{name}\" 正在创建中。",
failedToStartGeneration: "启动播客生成失败",
tryAgainMoment: "请稍后再试。",
},
settings: {
contentProcessing: "内容处理",
contentProcessingDesc: "配置文档和 URL 的处理方式",
docEngine: "文档处理引擎",
docEnginePlaceholder: "选择文档处理引擎",
urlEngine: "URL 处理引擎",
urlEnginePlaceholder: "选择 URL 处理引擎",
autoRecommended: "自动 (推荐)",
simple: "Simple",
docling: "Docling",
helpMeChoose: "帮助我选择",
docHelp: "· Docling: 速度稍慢但更准确,特别是包含表格和图像的文档。 · Simple: 直接提取内容而不进行格式化。 · 自动 (推荐): 优先尝试 Docling失败则回退至 Simple。",
firecrawl: "Firecrawl",
jina: "Jina",
urlHelp: "· Firecrawl: 强大的付费服务(有免费额度)。 · Jina: 优秀的备选方案,同样提供免费额度。 · Simple: 基础 HTTP 提取,在 JS 渲染的网站上可能会丢失内容。 · 自动 (推荐): 优先尝试 Firecrawl其次 Jina最后回退至 Simple。",
embeddingAndSearch: "嵌入与搜索",
embeddingAndSearchDesc: "配置搜索和向量嵌入选项",
defaultEmbeddingOption: "默认嵌入选项",
embeddingOptionPlaceholder: "选择嵌入选项",
ask: "询问",
always: "始终",
never: "从不",
embeddingHelp: "将内容进行向量嵌入可以让您和您的 AI 助手更容易找到它。如果您运行本地嵌入模型(如 Ollama建议开启。对于在线服务商只有在每天处理数百个文档时才需考虑成本。",
fileManagement: "文件管理",
fileManagementDesc: "配置文件的处理和存储选项",
autoDeleteFiles: "自动删除文件",
autoDeletePlaceholder: "选择自动删除选项",
filesHelp: "文件处理完成后,原始件不再需要。建议开启自动删除以节省存储空间。除非您将其作为主要存储位置(不建议),否则请选择“是”。",
loadFailed: "加载设置失败",
},
advanced: {
title: "高级工具",
desc: "面向进阶用户的调试和实用工具",
systemInfo: "系统信息",
systemInfoDesc: "查看底层系统组件的状态",
rebuildEmbeddings: "重建索引",
rebuildEmbeddingsDesc: "为所有来源重建向量索引",
rebuildWarning: "此操作可能非常耗时,具体取决于您的来源数量。它将清除现有的向量索引并重新为所有内容生成嵌入。",
startRebuild: "开始重建",
rebuilding: "正在重建...",
rebuildSuccess: "索引重建已成功启动",
currentVersion: "当前版本",
latestVersion: "最新版本",
status: "状态",
updateAvailable: "版本 {version} 可用",
updateAvailableDesc: "Open Notebook 的新版本可用。",
upToDate: "已是最新",
unknown: "未知",
viewOnGithub: "在 GitHub 上查看",
updateCheckFailed: "无法检查更新。GitHub 可能无法访问。",
rebuild: {
mode: "重建模式",
existing: "仅现有项",
all: "全部项",
existingDesc: "仅重新嵌入已有向量的项(速度较快,适用于切换模型)",
allDesc: "重新嵌入已有项 + 为缺失向量的项补全(速度较慢,较全面)",
include: "包含在重建中",
selectOneError: "请至少选择一种重建类型",
starting: "正在启动重建...",
startBtn: "开始重建",
queued: "排队中",
running: "正在提交任务...",
completed: "任务已提交!",
failed: "失败",
leavePageHint: "您可以离开此页面,后台将继续运行",
startNew: "开始新的重建",
itemsProcessed: "{processed}/{total} 任务已提交 ({percent}%)",
failedItems: "{count} 任务提交失败",
time: "耗时",
whenToRebuild: "我该何时重建索引?",
whenToRebuildAns: "当您切换嵌入模型、升级模型版本、怀疑数据损坏或进行了大批量内容导入后,建议执行重建。",
howLong: "重建需要多长时间?",
howLongAns: "耗时取决于项目总数、模型速度和 API 速率限制。本地模型(如 Ollama通常非常快。",
isSafe: "在使用应用时重建安全吗?",
isSafeAns: "是的,重建过程是安全的。它不会删除您的原始内容,仅会逐步替换向量数据。在大批量处理时,搜索速度可能会有轻微抖动。",
},
},
transformations: {
title: "内容转换规则",
desc: "转换规则是用于让大模型处理来源并提取见解、摘要等的提示词。",
workspace: "选择工作区",
playground: "实验室",
defaultPrompt: "默认全局提示词",
defaultPromptDesc: "该提示词将被添加到您所有的转换提示词中",
defaultPromptPlaceholder: "输入您的默认转换指令...",
saveDefault: "保存默认设置",
listTitle: "自定义转换",
createNew: "新建转换",
testInPlayground: "在实验室测试",
inputLabel: "输入文本",
inputPlaceholder: '请输入要转换的文本...',
outputLabel: '输出',
runTest: '运行转换',
running: '运行中...',
selectToStart: '选择一个转换规则开始',
name: '名称',
namePlaceholder: '唯一标识符,例如 key_topics',
titlePlaceholder: '显示名称,默认为名称',
promptPlaceholder: '编写驱动此转换的提示词...',
descriptionPlaceholder: '描述此转换的作用。',
suggestDefault: '新来源默认建议',
promptHint: '提示词应根据源内容编写。您可以要求模型总结、提取见解或生成表格等结构化输出。',
createSuccess: '转换规则创建成功',
updateSuccess: '转换规则更新成功',
deleteSuccess: '转换规则删除成功',
noTransformations: "暂无转换规则",
createOne: "创建一个转换规则以开始",
deleteDesc: "删除此转换无法撤销。",
selectModel: "选择模型",
deleteConfirm: "确定要删除此转换规则吗?",
model: "模型",
systemPrompt: "系统提示词",
type: "类型",
extraction: "提取",
summary: "摘要",
custom: "自定义",
saveChanges: "保存更改",
overrideModelDesc: "为此聊天会话覆盖默认模型。留空则使用系统默认。",
sessionUseReplacement: "此会话将使用 {name} 而不是默认模型。",
systemDefault: "系统默认",
},
models: {
title: "模型管理",
desc: "配置用于 Open Notebook 不同用途的 AI 模型",
failedToLoad: "加载模型数据失败",
language: "语言模型",
embedding: "嵌入模型",
tts: "文字转语音",
stt: "语音转文字",
providers: "服务商",
defaultModels: "默认模型",
status: "状态",
notConfigured: "未配置",
active: "活动",
inactive: "不活动",
configure: "配置",
saveChanges: "保存更改",
addModel: "添加模型",
modelName: "模型名称",
provider: "服务商",
apiKey: "API 密钥",
baseUrl: "基础 URL",
capabilities: "功能",
enabled: "已启用",
disabled: "已禁用",
deleteConfirm: "确定要删除此模型吗?",
deleteSuccess: "模型删除成功",
saveSuccess: "模型保存成功",
providerStatus: "服务商状态",
connectionOk: "连接正常",
connectionFailed: "连接失败",
changeEmbeddingWarning: "更改默认嵌入模型将影响新的来源。现有来源可能需要重建索引。",
changeEmbeddingTitle: "更改默认嵌入模型?",
aiProviders: "AI 服务商",
providerConfigDesc: "通过环境变量配置服务商以启用其模型。",
configuredCount: "已配置 {count} / {total}",
noModels: "暂无模型",
learnMore: "了解如何配置服务商 →",
seeLess: "收起",
seeAll: "查看全部 {count} 个服务商",
language_models: "语言模型",
embedding_models: "嵌入模型",
text_to_speech: "文字转语音",
speech_to_text: "语音转文字",
languageDesc: "聊天、内容转换和文本生成",
embeddingDesc: "语义搜索和向量嵌入",
ttsDesc: "根据文本生成音频",
sttDesc: "将语音转录为文本",
all: "全部",
noModelsConfigured: "未配置模型",
noProviderModelsConfigured: "未配置 {provider} 模型",
showMore: "显示更多 ({count})",
discoverModels: "发现模型",
noModelsFound: "未从此提供商找到模型",
modelType: "模型类型",
modelTypeHint: "选择要添加的模型类型。如果需要不同类型,请分批添加。",
deleteModel: "删除模型",
deleteModelDesc: "确定要删除模型 “{name}” 吗?该操作无法撤销。",
defaultAssignments: "默认模型分配",
defaultAssignmentsDesc: "配置用于 Open Notebook 不同用途的默认模型",
missingRequiredModels: "缺少必需的模型:{models}。如果没有这些模型Open Notebook 可能无法正常运行。",
selectModelPlaceholder: "选择一个模型",
requiredModelPlaceholder: "⚠️ 必需 - 请选择一个模型",
whichModelToChoose: "我该选择哪个模型?→",
chatModelLabel: "聊天模型",
chatModelDesc: "用于聊天对话",
transformationModelLabel: "转换模型",
transformationModelDesc: "用于摘要、见解和内容转换",
toolsModelLabel: "工具模型",
toolsModelDesc: "用于函数调用 - 推荐 OpenAI 或 Anthropic",
largeContextModelLabel: "大上下文模型",
largeContextModelDesc: "用于处理大文档 - 推荐 Gemini",
embeddingModelLabel: "嵌入模型",
embeddingModelDesc: "用于语义搜索和向量嵌入",
ttsModelLabel: "文字转语音模型",
ttsModelDesc: "用于生成播客",
sttModelLabel: "语音转文字模型",
sttModelDesc: "用于音频转录",
addSpecificModel: "添加 {type} 模型",
addSpecificModelDesc: "从可用服务商配置一个新的 {type} 模型。",
noProvidersForType: "暂无可用于 {type} 模型的服务商",
selectProviderPlaceholder: "选择服务商",
providerRequired: "服务商是必填项",
modelNameRequired: "模型名称是必填项",
modelRequired: "模型是必填项",
adding: "正在添加...",
azureHint: "对于 Azure请使用部署名称作为模型名称",
enterModelName: "输入模型名称",
embeddingChangeTitle: "嵌入模型变更",
embeddingChangeConfirm: "您即将将嵌入模型从 {from} 更改为 {to}。",
rebuildRequired: "重要提示:需要重建索引",
rebuildReason: "更改嵌入模型需要重建所有现有嵌入以保持一致性。如果不重建,您的搜索可能会返回错误或不完整的结果。",
whatHappensNext: "接下来会发生什么:",
step1: "您的默认嵌入模型将被更新",
step2: "在重新构建之前,现有的嵌入将保持不变",
step3: "新内容将使用新的嵌入模型",
step4: "您应该尽快重新构建嵌入",
proceedToRebuildPrompt: "您想现在前往“高级设置”页面开始重建索引吗?",
changeModelOnly: "仅更改模型",
changeAndRebuild: "更改并前往重建",
autoAssign: "自动分配默认值",
autoAssignDesc: "为每个槽位自动分配最佳可用模型",
autoAssigning: "正在分配...",
autoAssignSuccess: "已自动分配 {count} 个默认模型",
autoAssignNoModels: "没有可分配的模型。请先同步模型。",
autoAssignAlreadySet: "所有默认模型已配置",
testModel: "测试模型",
testModelSuccess: "模型测试通过",
testModelFailed: "模型测试失败",
testingModel: "正在测试模型...",
searchOrAddModel: "搜索或输入模型名称...",
addCustomModel: '添加 "{name}"',
},
apiKeys: {
title: "使用您自己的 API 密钥配置 AI",
description: "将 API 密钥安全地存储在数据库中,以在 Open Notebook 中启用 AI 服务商。",
loadFailed: "加载 API 密钥状态失败",
encryptionRequired: "未配置加密密钥",
encryptionRequiredDescription: "请将 OPEN_NOTEBOOK_ENCRYPTION_KEY 环境变量设置为任意密钥字符串,以启用将 API 密钥存储到数据库。",
configured: "已配置",
notConfigured: "未配置",
sourceDatabase: "数据库",
sourceEnvironment: "环境变量",
enterApiKey: "输入您的 API 密钥",
enterBaseUrl: "输入基础 URL",
saveSuccess: "API 密钥保存成功",
deleteSuccess: "API 密钥删除成功",
fromEnvironmentHint: "此密钥通过环境变量设置。保存新密钥将在数据库中覆盖它。",
migrationAvailable: "检测到环境变量",
migrationDescription: "{count} 个 API 密钥通过环境变量配置,可以迁移到数据库以便于管理。",
migrateToDatabase: "迁移到数据库",
migrating: "迁移中...",
migrationSuccess: "{count} 个 API 密钥迁移成功",
migrationErrors: "{count} 个密钥迁移失败",
migrationNothingToMigrate: "所有密钥已在数据库中",
serviceType: "服务类型",
serviceLlm: "语言模型 (LLM)",
serviceEmbedding: "嵌入",
serviceStt: "语音转文字 (STT)",
serviceTts: "文字转语音 (TTS)",
serviceEndpoints: "服务端点(可选)",
azureEndpointsHint: "如有需要,为每种服务类型配置不同的端点。",
endpointPlaceholder: "https://your-resource.openai.azure.com/",
openaiCompatibleHint: "配置 OpenAI 兼容的 API 端点。每种服务类型可以有自己的配置。",
baseUrlPlaceholder: "https://api.example.com/v1",
learnMore: "了解如何配置 API 密钥 →",
testConnection: "测试连接",
testing: "测试中...",
testSuccess: "连接成功",
testFailed: "连接测试失败",
syncModels: "同步模型",
syncing: "同步中...",
syncSuccess: "发现 {discovered} 个模型,新增 {new} 个",
syncNoNew: "发现 {count} 个模型,全部已注册",
syncFailed: "同步模型失败",
syncAllModels: "同步所有提供商",
syncAllSuccess: "在所有提供商中发现 {discovered} 个模型,新增 {new} 个",
modelsConfigured: "{count} 个模型",
noModelsConfigured: "无模型",
viewModels: "查看模型",
supportedTypes: "支持的类型",
typeLanguage: "语言",
typeEmbedding: "嵌入",
typeTts: "TTS",
typeStt: "STT",
apiEndpoint: "API 端点",
getApiKey: "获取 API 密钥",
vertexProject: "GCP 项目 ID",
vertexLocation: "区域",
vertexCredentials: "服务账户 JSON 路径",
vertexCredentialsHint: "容器内 Google Cloud 服务账户 JSON 文件的路径。",
// Multi-config translations
configsCount: "{count} 个配置",
configuredMultiple: "已配置",
addConfig: "添加配置",
editConfig: "编辑配置",
deleteConfig: "删除配置",
setAsDefault: "设为默认",
defaultBadge: "默认",
defaultDescription: "此提供商的默认配置",
configName: "配置名称",
configNameHint: "此配置的描述性名称(例如:'生产环境'、'开发环境'",
baseUrl: "基础 URL",
baseUrlHint: "默认:{url}",
baseUrlOverrideHint: "仅在需要覆盖提供商默认 API 端点时更改此项。",
ollamaApiKeyHint: "仅 Ollama Cloud 需要 API 密钥。本地 Ollama 请留空。",
noConfigs: "暂无配置",
noConfigsHint: "添加配置以开始使用此提供商",
deleteConfigConfirm: "确定要删除 '{name}' 吗?此操作无法撤销。",
setDefaultConfirm: "将 '{name}' 设为默认配置?",
configSaveSuccess: "配置保存成功",
configUpdateSuccess: "配置更新成功",
configDeleteSuccess: "配置删除成功",
configSetDefaultSuccess: "默认配置已更新",
apiKeyHint: "输入此配置的 API 密钥",
apiKeyEditHint: "留空以保留现有 API 密钥",
},
setupBanner: {
encryptionRequired: "未配置加密密钥",
encryptionRequiredDescription: "请设置 OPEN_NOTEBOOK_ENCRYPTION_KEY 环境变量以启用安全凭据存储。",
migrationAvailable: "API 密钥迁移可用",
migrationDescription: "{count} 个服务商的 API 密钥通过环境变量设置。将它们迁移到数据库以便于管理。",
goToSettings: "前往设置",
viewDocs: "查看文档",
},
}