## 新增 - 15 条主流供应商预设(Kimi Coding / Moonshot / Anthropic / DeepSeek / 智谱 GLM / z.ai / 阿里百炼 / MiniMax / StepFun / SiliconFlow / Novita / OpenRouter / OpenAI / Google AI Studio / 火山方舟),通过 PresetPickerModal 一键填表 - 供应商余额/套餐查询(卡片底部 UsageFooter):余额类 (DeepSeek / SiliconFlow / OpenRouter / StepFun / Novita) + 套餐类(Kimi For Coding / 智谱 GLM / MiniMax),5min stale TTL + force_refresh + 并发 ≤3 - Rust 端 services/ 模块(balance / coding_plan / usage_types), 参考 cc-switch(MIT,© Jason Young)实现 - query_provider_usage 命令:Rust 端从 config 加载 key, 不经 IPC 序列化 API key - usageKinds 持久化到 SQLite settings(JSON 数组), load 时合并回 config,导出 config.toml 时不写 - detect_provider 启发式:旧用户升级后自动获得账单支持 - save-time 校验:未完成供应商(缺 api_key / base_url / 模型) 保存时弹 confirm 列出原因;新增未提交 back 时静默 drop - docs/PROPOSAL-presets-and-usage.md(v0.4-draft 实施档) - docs/VERIFICATION-CHECKLIST.md(70+ 项手动验证清单) ## 修复 - handleDuplicateProvider 的 alias.slice 漏洞:老数据 非规范 alias 复制不再错位 - handleSelectPreset 不再 auto-save,半成品不会落盘 - handleSwitchProvider 校验取消时自动 refresh 回滚, 不会出现内存改 / 盘没动的脏态 ## 文档 - README / README_EN 致谢段补 cc-switch(预设 + 账单) - README 已知限制与后续建议段(/reload 上游限制调研结论) - i18n 补 5 条校验 key + 11 条预设 UI key + 12 条账单 key 详见 docs/PROPOSAL-presets-and-usage.md 与 docs/VERIFICATION-CHECKLIST.md
367 lines
12 KiB
TypeScript
367 lines
12 KiB
TypeScript
import type { TranslationKey } from "./zh";
|
||
|
||
export const enTranslations: Record<TranslationKey, string> = {
|
||
// App / global
|
||
appTitle: "Kimi Switch",
|
||
loading: "Loading...",
|
||
loadTimeout: "Loading is taking a while. Try restarting the app if it stays stuck.",
|
||
loadFailed: "Failed to load:",
|
||
retry: "Retry",
|
||
saveConfig: "Save Config",
|
||
reloadConfig: "Reload Config",
|
||
openConfigDir: "Open Config Dir",
|
||
unsavedConfirm: "You have unsaved changes. Are you sure you want to reload?",
|
||
validationNoApiKey: "Missing API key",
|
||
validationNoBaseUrl: "Missing base URL",
|
||
validationNoModels: "No models configured",
|
||
validationBlankModels: "Model entries with empty model id: {aliases}",
|
||
saveValidationConfirm:
|
||
"The following providers are not fully configured. Save anyway?\n\n{details}\n\n(Click OK to save to config.toml as-is; click Cancel to keep editing.)",
|
||
providerNotFound: "Provider not found",
|
||
backToList: "Back to list",
|
||
syncToOmp: "Sync to OMP",
|
||
syncedToOmp: "Synced to OMP: ",
|
||
ompOverwriteConfirm: "OMP already has provider \"{existing}\". Replace with \"{name}\"?",
|
||
deleteProviderConfirm: "Delete provider {name}?",
|
||
|
||
// Provider list
|
||
providers: "Providers",
|
||
dashboard: "Dashboard",
|
||
sessions: "Sessions",
|
||
addProvider: "Add Provider",
|
||
noProviders: "No providers yet",
|
||
addFirstProvider: "Add first provider",
|
||
noUrl: "No URL",
|
||
modelCount: "{count} models",
|
||
ompActive: "OMP Active",
|
||
defaultModel: "Default: {name}",
|
||
edit: "Edit",
|
||
delete: "Delete",
|
||
copyProvider: "Duplicate provider",
|
||
testConnectivity: "Test connectivity",
|
||
testing: "Testing...",
|
||
connectivityOk: "{name} reachable ({latency}ms)",
|
||
connectivitySlow: "{name} reachable but slow ({latency}ms)",
|
||
connectivityFail: "{name} unreachable: {error}",
|
||
copiedProvider: "Duplicated as {name}",
|
||
|
||
// Provider edit
|
||
editProvider: "Edit Provider",
|
||
back: "Back",
|
||
basicInfo: "Basic Info",
|
||
modelMapping: "Model Mapping",
|
||
configJson: "Config JSON",
|
||
providerName: "Provider Name",
|
||
note: "Note",
|
||
notePlaceholder: "e.g. company account",
|
||
officialUrl: "Official URL",
|
||
managedProvider: "Managed provider (no credentials needed)",
|
||
apiSettings: "API Settings",
|
||
apiFormat: "API Format",
|
||
authField: "Auth Field",
|
||
apiKey: "API Key",
|
||
show: "Show",
|
||
hide: "Hide",
|
||
requestUrl: "Request URL",
|
||
fullUrl: "Full URL",
|
||
baseUrlHint: "Enter a {type} API-compatible endpoint without a trailing slash.",
|
||
envPairs: "Env pairs",
|
||
addEnv: "+ Add",
|
||
modelMappingDesc: "Display name only affects the /model menu; 1M declares context capability for Kimi Code.",
|
||
oneClickSetup: "One-click setup",
|
||
fetchModels: "Fetch models",
|
||
fetchingModels: "Fetching...",
|
||
discoveredModels: "Discovered {count} models",
|
||
addSelected: "Add selected",
|
||
displayName: "Display name",
|
||
actualModel: "Actual model",
|
||
contextSize: "Context size",
|
||
supports1M: "Supports 1M",
|
||
default: "Default",
|
||
operation: "Operation",
|
||
isDefault: "Default",
|
||
setDefault: "Set default",
|
||
deleteModelConfirm: "Delete model {alias}?",
|
||
noModelMappings: "No model mappings",
|
||
addModelMapping: "+ Add model mapping",
|
||
readOnlyPreview: "Editable JSON",
|
||
apply: "Apply",
|
||
invalidJson: "Invalid JSON: {message}",
|
||
clickToSelectIcon: "Click to select icon",
|
||
clickToChangeIcon: "Click to change icon",
|
||
selectIcon: "Select icon",
|
||
clearIcon: "Clear icon",
|
||
iconPickerSearch: "Search icons",
|
||
iconPickerSearchPlaceholder: "Type an icon name...",
|
||
iconPickerNoResults: "No matching icons found",
|
||
|
||
// Agent / target
|
||
target: "Target",
|
||
targetKimi: "Kimi Code",
|
||
targetOmp: "OMP",
|
||
targetQwen: "Qwen Code",
|
||
agent: "Agent",
|
||
agentKimiCode: "Kimi Code",
|
||
agentPi: "Pi",
|
||
activate: "Activate",
|
||
activated: "Activated",
|
||
disabled: "Disabled",
|
||
switchTo: "Switch to",
|
||
inUse: "In use",
|
||
switchReloadHint: "After switching providers, run /reload in Kimi Code to apply the change.",
|
||
reloadCopiedHint: "Provider switched. /reload copied to clipboard; paste it in Kimi Code.",
|
||
unsavedChanges: "Unsaved changes",
|
||
qwenActivateNotImplemented: "Qwen Code activation will be implemented in a follow-up.",
|
||
agentSettings: "Global Settings",
|
||
enableThinking: "Enable thinking",
|
||
thinkingLevel: "Thinking level",
|
||
thinkingKeep: "Keep thinking content",
|
||
thinkingLow: "Low",
|
||
thinkingMedium: "Medium",
|
||
thinkingHigh: "High",
|
||
thinkingMax: "Max",
|
||
thinkingContextHint: "Thinking uses more context. Ensure the model context length and reserved size are sufficient.",
|
||
loopControlSettings: "Loop Control",
|
||
maxRetriesPerStep: "Max retries per step",
|
||
reservedContextSize: "Reserved context size",
|
||
backgroundSettings: "Background Tasks",
|
||
maxRunningTasks: "Max running tasks",
|
||
keepAliveOnExit: "Keep alive on exit",
|
||
permissionRules: "Permission Rules",
|
||
permissionDecision: "Decision",
|
||
permissionPattern: "Pattern",
|
||
permissionAllow: "Allow",
|
||
permissionDeny: "Deny",
|
||
permissionAsk: "Ask",
|
||
addRule: "+ Add rule",
|
||
addCommonRules: "Add common rules",
|
||
hooks: "Lifecycle Hooks",
|
||
hookEvent: "Event",
|
||
hookMatcher: "Matcher",
|
||
hookCommand: "Command",
|
||
hookTimeout: "Timeout",
|
||
addHook: "+ Add hook",
|
||
importConfig: "Import current config",
|
||
importConfigConfirm: "Importing will overwrite unsaved changes. Continue?",
|
||
importConfigFailed: "Import failed: {message}",
|
||
capabilities: "Capabilities",
|
||
fetchEnableThinking: "Enable thinking for fetched models",
|
||
capThinking: "Thinking",
|
||
capAlwaysThinking: "Always Thinking",
|
||
capImageIn: "Image Input",
|
||
capVideoIn: "Video Input",
|
||
capToolUse: "Tool Use",
|
||
customCapabilities: "Other capabilities (comma-separated)",
|
||
|
||
// Sessions
|
||
sessionsTitle: "Sessions",
|
||
sessionsSubtitle:
|
||
"Browse, preview, archive, or delete Kimi Code sessions by workspace. Archiving keeps data on disk.",
|
||
workspaces: "Workspaces",
|
||
workspaceIsolatedHint: "Sessions are isolated per workspace",
|
||
allWorkspaces: "All workspaces",
|
||
emptyWorkspace: "Empty",
|
||
deleteWorkspace: "Delete workspace",
|
||
noSessions: "No sessions",
|
||
statusActive: "Active",
|
||
statusArchived: "Archived",
|
||
statusAll: "All",
|
||
selectAll: "Select all",
|
||
deselectAll: "Deselect all",
|
||
selectedCount: "{n} selected",
|
||
archive: "Archive",
|
||
unarchive: "Unarchive",
|
||
sessionTitle: "Session",
|
||
workspace: "Workspace",
|
||
status: "Status",
|
||
size: "Size",
|
||
updated: "Updated",
|
||
actions: "Actions",
|
||
sessionsInView: "{n} sessions",
|
||
isolatedToWorkspace: "this workspace only",
|
||
openPreview: "Open preview",
|
||
scanning: "Scanning…",
|
||
refresh: "Refresh",
|
||
refreshing: "Refreshing…",
|
||
refreshed: "Refreshed",
|
||
cancel: "Cancel",
|
||
confirmDeleteTitle: "Delete session forever?",
|
||
confirmDeleteSession:
|
||
"This cannot be undone. Prefer archive if you only want it out of the way.",
|
||
confirmBulkTitle: "Delete selected forever?",
|
||
confirmBulkDelete: "Permanently delete {n} sessions. This cannot be undone.",
|
||
confirmDeleteWorkspaceTitle: "Delete empty workspace?",
|
||
confirmDeleteWorkspace: "Only workspaces with no sessions can be removed.",
|
||
deleteForever: "Delete forever",
|
||
previewTitle: "Session preview",
|
||
previewHint:
|
||
"Roles and truncated text only — secrets and raw tool dumps are omitted.",
|
||
previewEmpty: "No previewable messages",
|
||
previewTruncated: "Preview truncated",
|
||
roleUser: "User",
|
||
roleAssistant: "Assistant",
|
||
roleSystem: "System",
|
||
|
||
// Heatmap
|
||
noData: "No data",
|
||
heatLess: "Less",
|
||
heatMore: "More",
|
||
requests: "Requests",
|
||
cacheHitRate: "Cache hit rate",
|
||
|
||
// Daily detail modal
|
||
dayDetail: "Daily usage detail",
|
||
close: "Close",
|
||
totalTokens: "Total tokens",
|
||
cost: "Cost",
|
||
modelDistribution: "Model distribution",
|
||
providerDistribution: "Provider distribution",
|
||
modalEscHint: "Press Esc or click outside to close",
|
||
doubleClickHint: "Double-click for details",
|
||
|
||
// Languages
|
||
language: "Language",
|
||
zh: "中文",
|
||
en: "English",
|
||
|
||
// Theme & Settings
|
||
themeLight: "Light",
|
||
themeDark: "Dark",
|
||
themeAuto: "Auto",
|
||
settings: "Settings",
|
||
settingsTitle: "Settings",
|
||
settingsAppearance: "Appearance",
|
||
settingsUpdates: "Updates",
|
||
settingsAbout: "About",
|
||
checkUpdate: "Check for updates",
|
||
checking: "Checking…",
|
||
upToDate: "You're up to date",
|
||
updateAvailable: "Update available",
|
||
currentVersion: "Current version",
|
||
latestVersion: "Latest version",
|
||
downloadUpdate: "Download update",
|
||
downloading: "Downloading…",
|
||
downloadComplete: "Download complete, click to install",
|
||
install: "Install",
|
||
updateCheckFailed: "Update check failed",
|
||
lastChecked: "Last checked",
|
||
appDescription: "Windows desktop LLM provider config manager",
|
||
referenceProject: "Reference project",
|
||
|
||
// Validation errors
|
||
emptyProviderName: "Provider name is empty",
|
||
duplicateProviderName: "Duplicate provider name: {0}",
|
||
missingCredentials: "Provider '{0}' is missing credentials (api_key or env key)",
|
||
ambiguousCredentials: "Provider '{0}' has both direct and env credentials; only one source is allowed",
|
||
missingVertexProject: "Vertex provider '{0}' is missing GOOGLE_CLOUD_PROJECT or GOOGLE_CLOUD_LOCATION",
|
||
emptyModelAlias: "Model alias is empty",
|
||
duplicateModelAlias: "Duplicate model alias: {0}",
|
||
unknownModelProvider: "Model '{0}' references unknown provider '{1}'",
|
||
emptyModelId: "Model '{0}' has an empty model ID",
|
||
invalidMaxContextSize: "Model '{0}' has an invalid max_context_size",
|
||
|
||
// Dashboard — ranges / status
|
||
rangeToday: "Today",
|
||
range7d: "7d",
|
||
range30d: "30d",
|
||
rangeAll: "All",
|
||
dashLoadFailed: "Failed to load",
|
||
|
||
// Dashboard — KPI labels
|
||
kpiRequests: "Requests",
|
||
kpiInputOther: "Non-cached input",
|
||
kpiOutput: "Output",
|
||
kpiCacheRead: "Cache read",
|
||
kpiCacheCreation: "Cache creation",
|
||
kpiCacheHit: "Cache hit",
|
||
kpiCost: "Est. cost",
|
||
|
||
// Dashboard — cards
|
||
cardHeatmap: "Full-year heatmap",
|
||
cardHeatmapSub: "Coloured by token volume",
|
||
cardDailyTrend: "Usage trend",
|
||
cardDailyTrendSubCapped: "Last 30 days · {n} days total",
|
||
tabModelTrend: "Model usage trend",
|
||
tabProviderTrend: "Provider–model usage trend",
|
||
providerUnknown: "Unknown provider",
|
||
cardDailyTrendSub: "{n} days",
|
||
cardModelUsage: "Model usage",
|
||
cardModelUsageSub: "{n} models",
|
||
cardRecent: "Recent requests",
|
||
cardRecentCapped: "Showing first {n} / {m}",
|
||
cardRecentCount: "{n} entries",
|
||
|
||
// Dashboard — table columns / units
|
||
colModel: "Model",
|
||
colTokens: "Tokens",
|
||
colCacheHit: "Cache hit",
|
||
colTime: "Time",
|
||
colInput: "Input",
|
||
colOutput: "Output",
|
||
colCacheRead: "Cache read",
|
||
unitTimes: "requests",
|
||
estimate: "est.",
|
||
collapse: "Collapse",
|
||
expandAll: "Expand all ({n})",
|
||
|
||
// Dashboard — pagination
|
||
paginationPage: "Page {x} / {y}",
|
||
paginationRange: "{x}–{y}",
|
||
paginationPerPage: "{n} per page",
|
||
pageFirst: "First",
|
||
pagePrev: "Previous",
|
||
pageNext: "Next",
|
||
pageLast: "Last",
|
||
|
||
// Dashboard — footer / attribution
|
||
footerScanned: "Scanned {n} files · {m} records",
|
||
dashboardAttribution: "Dashboard ported from",
|
||
sessionsAttribution: "Session manager ported from",
|
||
attributionSuffix: "(MIT, © JochenYang)",
|
||
|
||
// Sessions — preview
|
||
previewCollapseChars: "Collapse · {n} chars",
|
||
previewExpandChars: "Expand · {n} chars",
|
||
|
||
// Provider presets
|
||
presetPickerTitle: "Choose a provider preset",
|
||
presetSearchPlaceholder: "Search presets...",
|
||
presetSortOriginal: "Default",
|
||
presetSortAlpha: "A-Z",
|
||
presetNoResults: "No matching presets",
|
||
presetCustomConfig: "+ Custom configuration",
|
||
presetFooterHint: "Presets only pre-fill the form; every field stays editable afterwards.",
|
||
presetCategoryOfficial: "Official",
|
||
presetCategoryCnOfficial: "China",
|
||
presetCategoryThirdParty: "Third-party",
|
||
presetCategoryAggregator: "Aggregator",
|
||
presetNameAnthropic: "Anthropic",
|
||
presetNameKimiCoding: "Kimi For Coding",
|
||
presetNameMoonshot: "Moonshot Platform",
|
||
presetNameDeepseek: "DeepSeek",
|
||
presetNameZhipu: "Zhipu GLM",
|
||
presetNameZai: "z.ai (Zhipu Global)",
|
||
presetNameBailian: "Alibaba Bailian",
|
||
presetNameMinimax: "MiniMax",
|
||
presetNameStepfun: "StepFun",
|
||
presetNameSiliconflow: "SiliconFlow",
|
||
presetNameNovita: "Novita AI",
|
||
presetNameOpenrouter: "OpenRouter",
|
||
presetNameOpenai: "OpenAI",
|
||
presetNameGoogleGenai: "Google AI Studio",
|
||
presetNameVolcengine: "Volcengine Ark",
|
||
|
||
// Provider usage
|
||
usageBalance: "Balance",
|
||
usageUsed: "used",
|
||
usageRemaining: "left",
|
||
usageRefresh: "Refresh",
|
||
usageRetry: "Retry",
|
||
usageQueryFailed: "Query failed",
|
||
usageNetworkError: "Network error",
|
||
usageInvalidKey: "Invalid API key",
|
||
usageResetIn: "resets in {time}",
|
||
usageResetDone: "reset",
|
||
usageLoading: "Querying…",
|
||
};
|