diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index a6269686d6..1dcf49ab91 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -914,26 +914,6 @@ "when": "Use when long sessions must survive account rotation without losing the working context.", "avoid": "Avoid when account switching is rare or when you do not want extra summarization requests.", "example": "Example: Codex sessions that rotate across multiple accounts near quota exhaustion." - }, - "fill-first": { - "when": "Use when you want to fully exhaust one provider's quota before moving to the next.", - "avoid": "Avoid when you need request-level load balancing between providers.", - "example": "Example: Use up all $200 of Deepgram credits before falling back to Groq." - }, - "auto": { - "when": "Use when you have one preferred model and only want fallback on failure.", - "avoid": "Avoid when you need balanced load between models.", - "example": "Example: Primary coding model with cheaper backup for outages." - }, - "lkgp": { - "when": "Use when you have one preferred model and only want fallback on failure.", - "avoid": "Avoid when you need balanced load between models.", - "example": "Example: Primary coding model with cheaper backup for outages." - }, - "context-optimized": { - "when": "Use when you have one preferred model and only want fallback on failure.", - "avoid": "Avoid when you need balanced load between models.", - "example": "Example: Primary coding model with cheaper backup for outages." } }, "advancedHelp": { @@ -1013,25 +993,6 @@ "candidatePoolHint": "Select which providers this engine should evaluate. Leave empty to use all active providers.", "candidatePoolEmpty": "No active providers available yet.", "candidatePoolAllProviders": "All providers", - "builderStagesDescription": "Move through the stages in order to define the combo, build the steps, choose the routing strategy and review the result.", - "builderStepsDescription": "Build each combo step in sequence: provider, model, then account. This allows repeating the same provider and model with different accounts.", - "selectProvider": "Select Provider", - "selectProviderPlaceholder": "Select provider", - "selectModel": "Select Model", - "selectModelPlaceholder": "Select provider first", - "selectAccount": "Select Account", - "autoSelectAccount": "Auto-select account at runtime", - "previewNextStep": "Choose provider and model to preview the next step.", - "addStep": "Add Step", - "comboReference": "Combo Reference", - "selectComboToReference": "Select an existing combo to reference", - "addComboReference": "Add Combo Reference", - "browseLegacyCatalog": "Browse legacy model catalog", - "addStepBeforeContinue": "Add at least one step before continuing to the next stage.", - "modePackPerformance": "Performance", - "modePackBudget": "Budget", - "modePackBalanced": "Balanced", - "modePackCustom": "Custom", "modePackLabel": "Mode Pack", "routerStrategyLabel": "Router Strategy", "strategyRules": "Rules (6-Factor Scoring)", @@ -1091,54 +1052,12 @@ "tip2": "Keep a quality fallback for hard prompts.", "tip3": "Use for batch/background jobs where cost is the main KPI." }, - "fill-first": { - "title": "Quota drain strategy", - "description": "Exhausts one provider's quota before moving to the next in chain.", - "tip1": "Order models by free quota size — biggest first.", - "tip2": "Enable health checks to skip drained providers.", - "tip3": "Ideal for free-tier stacking (Deepgram → Groq → NIM)." - }, - "p2c": { - "title": "Power-of-Two-Choices", - "description": "Picks the less-loaded of two random candidates per request — low latency at scale.", - "tip1": "Use with 4+ models for best effect.", - "tip2": "Requires latency telemetry enabled in Settings.", - "tip3": "Great replacement for round-robin in high-throughput combos." - }, - "context-relay": { - "title": "Session continuity first", - "description": "Best when account rotation is expected and the next account must inherit a condensed task summary.", - "tip1": "Use with providers that rotate accounts for the same model family.", - "tip2": "Keep the handoff threshold below the hard quota cutoff to give the summary time to generate.", - "tip3": "Set a dedicated summary model only when the primary model is too expensive or unstable." - }, "strict-random": { "title": "Shuffle deck distribution", "description": "Each model is used exactly once per cycle before reshuffling.", "tip1": "Use at least 2 models for meaningful distribution.", "tip2": "Works best with equivalent-performance models.", "tip3": "Ideal for load balancing across multiple API accounts." - }, - "auto": { - "title": "Fail-safe baseline", - "description": "Use one primary model and keep fallback chain short and reliable.", - "tip1": "Put your most reliable model first.", - "tip2": "Keep 1-2 backup models with similar quality.", - "tip3": "Use safe retries to absorb transient provider failures." - }, - "lkgp": { - "title": "Fail-safe baseline", - "description": "Use one primary model and keep fallback chain short and reliable.", - "tip1": "Put your most reliable model first.", - "tip2": "Keep 1-2 backup models with similar quality.", - "tip3": "Use safe retries to absorb transient provider failures." - }, - "context-optimized": { - "title": "Fail-safe baseline", - "description": "Use one primary model and keep fallback chain short and reliable.", - "tip1": "Put your most reliable model first.", - "tip2": "Keep 1-2 backup models with similar quality.", - "tip3": "Use safe retries to absorb transient provider failures." } }, "templateFreeStack": "Free Stack ($0)", @@ -3399,258 +3318,5 @@ "deduplicatedRequests": "Deduplicated Requests", "savedCalls": "Saved API Calls", "totalProcessed": "Total Requests Processed" - }, - "proxyConfigModal": { - "levelGlobal": "Global", - "levelProvider": "Provider", - "levelCombo": "Combo", - "levelKey": "Key", - "levelDirect": "Direct (none)", - "titleGlobal": "Global Proxy Configuration", - "titleLevel": "{level} Proxy — {label}", - "loading": "Loading proxy configuration...", - "inheritingFrom": "Inheriting from", - "source": "Source", - "savedProxy": "Saved Proxy", - "custom": "Custom", - "selectSavedProxyPlaceholder": "Select saved proxy...", - "proxyType": "Proxy Type", - "host": "Host", - "hostPlaceholder": "1.2.3.4 or proxy.example.com", - "port": "Port", - "authOptional": "Authentication (optional)", - "username": "Username", - "usernamePlaceholder": "Username", - "password": "Password", - "passwordPlaceholder": "Password", - "connected": "Connected", - "ip": "IP:", - "connectionFailed": "Connection failed", - "testConnection": "Test Connection", - "clear": "Clear", - "cancel": "Cancel", - "save": "Save", - "errorSelectSavedProxy": "Select a saved proxy before saving.", - "errorSelectProxyFirst": "Select a saved proxy first.", - "errorProxyNotFound": "Selected proxy not found.", - "errorClearSavedProxy": "Failed to clear saved proxy", - "errorSaveProxy": "Failed to save proxy configuration", - "errorClearProxy": "Failed to clear proxy configuration", - "errorSocks5Hidden": "SOCKS5 is configured but hidden because NEXT_PUBLIC_ENABLE_SOCKS5_PROXY=false." - }, - "oauthModal": { - "title": "Connect {providerName}", - "waiting": "Waiting for Authorization", - "completeAuthInPopup": "Complete the authorization in the popup window.", - "popupClosedHint": "If the popup closes without redirecting back (e.g. Qoder), this dialog will automatically switch to manual URL input mode.", - "popupBlocked": "Popup blocked? Enter URL manually", - "deviceCodeVisitUrl": "Visit the URL below and enter the code:", - "deviceCodeVerificationUrl": "Verification URL", - "deviceCodeYourCode": "Your Code", - "deviceCodeWaiting": "Waiting for authorization...", - "googleOAuthWarning": "Remote access + Google OAuth: The default credentials only accept redirects to localhost. After authorizing, your browser will try to open localhost — copy that full URL and paste it below. For fully remote use without this manual step, configure your own OAuth credentials.", - "remoteAccessInfo": "Remote access: Since you're accessing OmniRoute remotely, after authorizing you'll see an error page (localhost not found). That's expected — just copy the full URL from your browser's address bar and paste it below.", - "step1OpenUrl": "Step 1: Open this URL in your browser", - "copy": "Copy", - "step2PasteCallback": "Step 2: Paste the callback URL or auth code here", - "step2Hint": "After authorization, paste the full callback URL. For Claude Code and Cline, you can also paste the Authentication Code directly, for example code#state.", - "connect": "Connect", - "cancel": "Cancel", - "success": "Connected Successfully!", - "successMessage": "Your {providerName} account has been connected.", - "done": "Done", - "error": "Connection Failed", - "tryAgain": "Try Again" - }, - "cursorAuthModal": { - "title": "Connect Cursor IDE", - "autoDetecting": "Auto-detecting tokens...", - "readingFromCursor": "Reading from Cursor IDE or cursor-agent", - "tokensAutoDetected": "Tokens auto-detected from Cursor IDE successfully!", - "cursorNotDetected": "Cursor IDE not detected. Please paste your tokens manually.", - "accessToken": "Access Token", - "required": "*", - "accessTokenPlaceholder": "Access token will be auto-filled...", - "machineId": "Machine ID", - "optional": "(optional)", - "machineIdPlaceholder": "Machine ID will be auto-filled...", - "importing": "Importing...", - "importToken": "Import Token", - "cancel": "Cancel", - "errorAutoDetect": "Could not auto-detect tokens", - "errorAutoDetectFailed": "Failed to auto-detect tokens", - "errorEnterToken": "Please enter an access token", - "errorImportFailed": "Import failed" - }, - "pricingModal": { - "title": "Pricing Configuration", - "loading": "Loading pricing data...", - "pricingRatesFormat": "Pricing Rates Format", - "ratesDescription": "All rates are in dollars per million tokens ($/1M tokens). Example: Input rate of 2.50 means $2.50 per 1,000,000 input tokens.", - "model": "Model", - "input": "Input", - "output": "Output", - "cached": "Cached", - "reasoning": "Reasoning", - "cacheCreation": "Cache Creation", - "noPricingData": "No pricing data available", - "resetToDefaults": "Reset to Defaults", - "cancel": "Cancel", - "saving": "Saving...", - "saveChanges": "Save Changes", - "resetConfirm": "Reset all pricing to defaults? This cannot be undone.", - "errorSaveFailed": "Failed to save pricing", - "errorResetFailed": "Failed to reset pricing" - }, - "proxyRegistry": { - "title": "Proxy Registry", - "description": "Store reusable proxies and track assignments.", - "importLegacy": "Import Legacy", - "bulkAssign": "Bulk Assign", - "addProxy": "Add Proxy", - "loading": "Loading proxies...", - "noProxies": "No saved proxies yet.", - "tableName": "Name", - "tableEndpoint": "Endpoint", - "tableStatus": "Status", - "tableHealth": "Health (24h)", - "tableUsage": "Usage", - "tableActions": "Actions", - "test": "Test", - "edit": "Edit", - "delete": "Delete", - "modalCreateTitle": "Create Proxy", - "modalEditTitle": "Edit Proxy", - "labelName": "Name", - "labelType": "Type", - "labelHost": "Host", - "labelPort": "Port", - "labelUsername": "Username", - "labelPassword": "Password", - "labelRegion": "Region", - "labelStatus": "Status", - "labelNotes": "Notes", - "usernamePlaceholderEdit": "Leave blank to keep current username", - "passwordPlaceholderEdit": "Leave blank to keep current password", - "statusActive": "active", - "statusInactive": "inactive", - "cancel": "Cancel", - "save": "Save", - "bulkModalTitle": "Bulk Proxy Assignment", - "bulkLabelScope": "Scope", - "bulkLabelProxy": "Proxy", - "bulkClearAssignment": "(clear assignment)", - "bulkLabelScopeIds": "Scope IDs (comma or newline)", - "bulkScopeIdsPlaceholder": "provider-openai,provider-anthropic", - "bulkApply": "Apply", - "errorLoadFailed": "Failed to load proxy registry", - "errorNameHostRequired": "Name and host are required", - "errorSaveFailed": "Failed to save proxy", - "errorDeleteFailed": "Failed to delete proxy", - "errorForceDeleteConfirm": "This proxy is still assigned. Force delete and remove all assignments?", - "errorMigrateFailed": "Failed to migrate legacy proxy config", - "errorBulkFailed": "Failed to run bulk assignment", - "success": "✓", - "failure": "✗", - "failed": "failed", - "successRate": "{rate}% success", - "avgLatency": "{latency} ms avg", - "assignmentsCount": "{count} assignment(s)", - "noData": "—", - "testSuccess": "✓ {ip}", - "testLatency": "{latency}ms", - "testFailure": "✗ {error}" - }, - "playground": { - "title": "Model Playground", - "description": "Test any model directly from the dashboard. Pick a provider, model, and endpoint type, then send a request to see the raw response.", - "endpoint": "Endpoint", - "provider": "Provider", - "model": "Model", - "accountKey": "Account / Key", - "autoAccounts": "Auto ({count} accounts)", - "noAccounts": "No accounts", - "send": "Send", - "cancel": "Cancel", - "audioFile": "Audio File", - "attachImages": "Attach Images (Vision)", - "multipartFormData": "multipart/form-data", - "upToImages": "up to 4 images", - "selectAudioFile": "Select an audio file to transcribe (mp3, wav, m4a, ogg, flac…)", - "clearAll": "Clear all", - "request": "Request", - "response": "Response", - "transcription": "Transcription", - "copy": "Copy", - "resetToDefault": "Reset to default", - "downloadAudio": "Download audio", - "copyText": "Copy text", - "transcriptionHint": "Transcription uses multipart/form-data. Upload the audio file above — JSON below controls extra params (model, language).", - "imagesGenerated": "{count} image{count, plural, one {} other {s}} generated", - "generatedImage": "Generated image {index}", - "save": "Save", - "endpointOptions": { - "chat": "Chat Completions", - "responses": "Responses", - "images": "Image Generation", - "embeddings": "Embeddings", - "speech": "Text to Speech", - "transcription": "Audio Transcription", - "video": "Video Generation", - "music": "Music Generation", - "rerank": "Rerank", - "search": "Web Search" - } - }, - "requestLogger": { - "recording": "Recording", - "paused": "Paused", - "pipelineLogsOn": "Pipeline Logs On", - "pipelineLogsOff": "Pipeline Logs Off", - "updatingPipelineLogs": "Updating pipeline logs...", - "searchPlaceholder": "Search model, provider, account, API key, combo...", - "allProviders": "All Providers", - "allModels": "All Models", - "allAccounts": "All Accounts", - "allApiKeys": "All API Keys", - "total": "total", - "ok": "OK", - "err": "ERR", - "combo": "combo", - "keys": "keys", - "shown": "shown", - "sortNewest": "Newest", - "sortOldest": "Oldest", - "sortTokensDesc": "Tokens ↓", - "sortTokensAsc": "Tokens ↑", - "sortDurationDesc": "Duration ↓", - "sortDurationAsc": "Duration ↑", - "sortStatusDesc": "Status ↓", - "sortStatusAsc": "Status ↑", - "sortModelAsc": "Model A-Z", - "sortModelDesc": "Model Z-A", - "statusFilters": { - "all": "All", - "error": "Errors", - "success": "Success", - "combo": "Combo" - }, - "columns": { - "status": "Status", - "model": "Model", - "requested": "Requested", - "provider": "Provider", - "protocol": "Req Protocol", - "account": "Account", - "apiKey": "API Key", - "combo": "Combo", - "tokens": "Tokens", - "duration": "Duration", - "time": "Time" - }, - "loadingLogs": "Loading logs...", - "noLogs": "No logs recorded yet. Make some API calls to see them here.", - "noMatchingLogs": "No logs match the current filters.", - "callLogsInfo": "Call logs are also saved as JSON files to {dataDir} and rotated by {retentionDays} and {maxEntries}." } } diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index f28f0c058f..171bd2152e 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -1163,6 +1163,28 @@ "reorderHandle": "拖拽排序", "failedReorder": "模型重排序失败", "builderFlowTitle": "组合构建流程", + "builderStage": { + "basics": { + "label": "基础", + "description": "名称和起始模板" + }, + "steps": { + "label": "步骤", + "description": "提供商、模型和账户选择" + }, + "strategy": { + "label": "策略", + "description": "路由行为和高级设置" + }, + "intelligent": { + "label": "智能路由", + "description": "自动路由候选池、预设和评分" + }, + "review": { + "label": "审查", + "description": "保存前的最终验证" + } + }, "builderStageVisited": "阶段已完成", "builderStageCurrent": "当前阶段", "builderStagePending": "待处理",