feat(settings): reorganize the settings dialog and the model settings

Tabs Models, General, Drawing and About, each with a fixed title row.

The models tab becomes three pages: the user's providers with one status
each and the server's models; a searchable picker of all 24 providers in
four groups; and a provider page in three steps (connection, models,
test). A new provider gets its first suggested model, and a passing test
offers to use the model in the chat. Bedrock asks for one way of signing
in, with an optional session token for temporary access keys.

The composer's model picker lists every model, marking untested and
failed ones, and can open the provider picker. A chat error that offers
model settings opens the provider the request went to.
This commit is contained in:
dayuan.jiang
2026-10-08 17:44:08 +09:00
parent c513d1a0c2
commit 69fb66804d
32 changed files with 4237 additions and 1730 deletions
+86 -33
View File
@@ -120,9 +120,7 @@
"customSystemMessagePlaceholder": "e.g., Always use blue color scheme for diagrams...",
"maxOutputTokens": "Max output tokens",
"maxOutputTokensDescription": "Budget for one reply, shared by thinking and the diagram XML. Raise it if the AI keeps thinking and no diagram appears. Leave empty for the default.",
"tabModels": "Models & keys",
"tabAppearance": "Appearance",
"tabAdvanced": "Advanced",
"tabModels": "Models",
"tabAbout": "About",
"themeLight": "Light",
"themeDarkMode": "Dark",
@@ -131,7 +129,11 @@
"proxyInvalid": "Proxy addresses must start with http:// or https://",
"proxyFailed": "Couldn't apply the proxy settings",
"appVersion": "Version",
"projectWebsite": "Project website"
"projectWebsite": "Project website",
"tabGeneral": "General",
"tabDrawing": "Drawing",
"sectionInterface": "Interface",
"sectionAccess": "Access"
},
"save": {
"title": "Export diagram",
@@ -351,24 +353,16 @@
},
"modelConfig": {
"configure": "Configure",
"addProvider": "Add Provider",
"addProvider": "Add provider",
"addModel": "Add Model",
"modelId": "Model ID",
"modelLabel": "Display Label",
"streaming": "Enable Streaming",
"deleteProvider": "Delete Provider",
"deleteProvider": "Delete provider",
"deleteModel": "Delete Model",
"noModels": "No models configured. Add a model to get started.",
"selectProvider": "Select a provider or add a new one",
"configureMultiple": "Configure multiple AI providers and switch between them easily",
"apiKeyStored": "API keys are stored locally in your browser",
"test": "Test",
"validationError": "Validation failed",
"addModelFirst": "Add at least one model to validate",
"providers": "Providers",
"addProviderHint": "No providers yet",
"verified": "Verified",
"configuration": "Configuration",
"validationError": "The test failed",
"addModelFirst": "Add a model first.",
"displayName": "Display Name",
"bedrockApiKey": "Bedrock API key",
"bedrockApiKeyHint": "With an API key, the access keys below are not needed.",
@@ -376,13 +370,12 @@
"awsSecretAccessKey": "AWS Secret Access Key",
"awsRegion": "AWS Region",
"selectRegion": "Select region",
"apiKey": "API Key",
"apiKey": "API key",
"enterApiKey": "Enter your API key",
"enterSecretKey": "Enter your secret access key",
"baseUrl": "Base URL",
"optional": "(optional)",
"getApiKey": "Get API key",
"fetchModels": "Fetch models from the provider",
"noTools": "no tool calls",
"mayNotDraw": "models.dev lists no tool call support for this model, so it may not be able to draw.",
"requestUrl": "Requests go to {url}",
@@ -393,17 +386,11 @@
"models": "Models",
"customModelId": "Custom model ID...",
"allAdded": "All added",
"suggested": "Suggested",
"noModelsConfigured": "No models configured",
"modelIdEmpty": "Model ID cannot be empty",
"modelIdExists": "This model ID already exists",
"configureProviders": "Set up AI providers",
"selectProviderHint": "Select a provider from the list or add a new one to configure API keys and models",
"deleteConfirmDesc": "Are you sure you want to delete {name}? This will remove all configured models and cannot be undone.",
"typeToConfirm": "Type \"{name}\" to confirm",
"typeProviderName": "Type provider name...",
"modelsConfiguredCount": "{count} model(s) configured",
"validationFailedCount": "{count} model(s) failed validation",
"typeProviderName": "Type the provider name...",
"requestFailed": "Request failed ({status})",
"cancel": "Cancel",
"delete": "Delete",
@@ -411,22 +398,88 @@
"usingServerDefault": "Using server default model",
"selectModel": "Select Model",
"searchModels": "Search models...",
"noVerifiedModels": "No verified models. Test your models first.",
"noModelsFound": "No models found.",
"default": "Default",
"serverDefault": "Server Default",
"serverModels": "Server Models",
"userModels": "User Models",
"configureModels": "Configure Models...",
"onlyVerifiedShown": "Only verified models are shown",
"showUnvalidatedModels": "Show unvalidated models",
"allModelsShown": "All models are shown (including unvalidated)",
"unvalidatedModelWarning": "This model has not been validated",
"serverDefaultModel": "Server default model",
"showValue": "Show value",
"hideValue": "Hide value",
"noProvidersTitle": "Using the model set up on this server",
"noProvidersHint": "To use other models, add a provider with your own API key below the list on the left."
"myProviders": "My providers",
"inUse": "In use",
"listSeparator": ", ",
"serverModelsTitle": "Models from this server",
"serverDefaultSummary": "No API key needed: the server's default model.",
"statusError": "{count} failed",
"statusIncomplete": "Not set up yet",
"statusUntested": "{count} untested",
"statusOk": "{count} working",
"noModelsYet": "No models yet",
"keysStayLocal": "API keys stay in this browser on this device and go to the server only with your requests.",
"useOwnKey": "Use your own API key",
"useOwnKeyHint": "Add a provider to use its models from the chat's model picker. Pick one to start:",
"viewAllProviders": "See all {count} providers",
"searchProviders": "Search providers, e.g. DeepSeek, Qwen, Ollama",
"noProvidersFound": "No provider matches.",
"groupVendors": "Model makers",
"groupAggregators": "Aggregators",
"groupCloud": "Cloud platforms",
"groupSelfHosted": "Self-hosted",
"noteBedrock": "AWS credentials",
"noteVertex": "Express mode key",
"noteAzure": "Key and resource URL",
"noteEdgeone": "No key needed",
"noteOllama": "Key optional",
"noteSglang": "Your server's URL",
"added": "Added",
"awsCredentials": "AWS credentials",
"bedrockAuthApiKey": "Bedrock API key",
"bedrockAuthAccessKey": "Access keys",
"moreOptions": "More options: base URL, display name",
"moreOptionsName": "More options: display name",
"keyRejected": "The provider rejected this API key. Check that the key above was copied in full.",
"modelNotFound": "The provider can't find this model ID. Check its spelling.",
"modelWorks": "Works",
"modelWorksTime": "Works · {seconds} s",
"modelFailed": "Failed",
"modelUntested": "Untested",
"needKey": "Fill in the API key first.",
"needAws": "Fill in the AWS credentials and region first.",
"needModel": "Add a model first.",
"stepConnect": "Connection",
"edgeoneNoKey": "EdgeOne Pages uses the model service that comes with this site's deployment: no API key needed.",
"stepModels": "Models",
"fetchAllModels": "Get all models from {name}",
"suggestedLabel": "Suggested:",
"orTypeModelId": "Or type another model ID",
"add": "Add",
"browseModels": "Browse models",
"stepTest": "Test",
"testHint": "Sends each model a very short message to check that the key and the model work.",
"testOne": "Test {model}",
"testAll": "Test all {count} models",
"testPassedOne": "{model} works",
"testPassedAll": "All {count} models work",
"answeredIn": "(answered in {seconds} s)",
"useInChat": "Use {model} in the chat",
"backToProviders": "Back to providers",
"deleteProviderOnly": "Delete {name}",
"addProviderEntry": "Add a provider…",
"awsKeysRejected": "AWS rejected these access keys. Check that both were copied in full.",
"needAzure": "Fill in the API key and your Azure resource's base URL first.",
"validationFailedCountOne": "{count} model failed the test",
"validationFailedCountOther": "{count} models failed the test",
"deleteProviderNamedOne": "Delete {name} and its model",
"deleteProviderNamedOther": "Delete {name} and its {count} models",
"serverModelsSummaryOne": "No API key needed. {count} model: {names}",
"serverModelsSummaryOther": "No API key needed. {count} models: {names}",
"noModelsReturned": "The provider returned no models.",
"awsSessionToken": "AWS session token (optional)",
"awsSessionTokenHint": "Only for temporary credentials: access keys that start with ASIA.",
"bedrockBothSaved": "This provider also keeps an access key pair, unused while there is an API key.",
"removeAccessKeys": "Remove the access keys"
},
"admin": {
"title": "Admin Settings",
@@ -612,7 +665,7 @@
"failed": "This attempt failed",
"failedRetrying": "This attempt failed, trying again",
"stopped": "Stopped",
"truncatedHint": "The reply hit the output limit before the diagram was complete. Ask for a simpler diagram, or raise Max output tokens in Settings > Advanced.",
"truncatedHint": "The reply hit the output limit before the diagram was complete. Ask for a simpler diagram, or raise Max output tokens in Settings > Drawing.",
"noChanges": "No visible changes",
"listSeparator": ", ",
"shapesAddedOne": "added 1 shape",
+82 -29
View File
@@ -120,9 +120,7 @@
"customSystemMessagePlaceholder": "例:ダイアグラムには常に青色のカラースキームを使用...",
"maxOutputTokens": "最大出力トークン数",
"maxOutputTokensDescription": "1回の応答の予算で、思考過程とダイアグラムの XML が共有します。AI が考え続けてダイアグラムが生成されない場合は大きくしてください。空欄ならデフォルト値を使います。",
"tabModels": "モデルとキー",
"tabAppearance": "外観",
"tabAdvanced": "詳細",
"tabModels": "モデル",
"tabAbout": "このアプリについて",
"themeLight": "ライト",
"themeDarkMode": "ダーク",
@@ -131,7 +129,11 @@
"proxyInvalid": "プロキシのアドレスは http:// または https:// で始めてください",
"proxyFailed": "プロキシ設定を適用できませんでした",
"appVersion": "バージョン",
"projectWebsite": "プロジェクトのサイト"
"projectWebsite": "プロジェクトのサイト",
"tabGeneral": "一般",
"tabDrawing": "描画",
"sectionInterface": "表示",
"sectionAccess": "アクセス"
},
"save": {
"title": "図をエクスポート",
@@ -314,16 +316,8 @@
"deleteProvider": "プロバイダーを削除",
"deleteModel": "モデルを削除",
"noModels": "モデルが設定されていません。モデルを追加してください。",
"selectProvider": "プロバイダーを選択または追加してください",
"configureMultiple": "複数のAIプロバイダーを設定して簡単に切り替え",
"apiKeyStored": "APIキーはブラウザにローカル保存されます",
"test": "テスト",
"validationError": "検証に失敗しました",
"addModelFirst": "検証するには少なくとも1つのモデルを追加してください",
"providers": "プロバイダー",
"addProviderHint": "プロバイダーはまだありません",
"verified": "検証済み",
"configuration": "設定",
"validationError": "テストに失敗しました",
"addModelFirst": "先にモデルを追加してください。",
"displayName": "表示名",
"bedrockApiKey": "Bedrock API キー",
"bedrockApiKeyHint": "API キーを入力すれば、下のアクセスキーは不要です。",
@@ -337,7 +331,6 @@
"baseUrl": "ベース URL",
"optional": "(オプション)",
"getApiKey": "API キーを取得",
"fetchModels": "プロバイダーからモデル一覧を取得",
"noTools": "ツール呼び出し非対応",
"mayNotDraw": "models.dev によると、このモデルはツール呼び出しに対応していないため、作図できない可能性があります。",
"requestUrl": "リクエスト先: {url}",
@@ -348,17 +341,11 @@
"models": "モデル",
"customModelId": "カスタムモデル ID...",
"allAdded": "すべて追加済み",
"suggested": "おすすめ",
"noModelsConfigured": "モデルが設定されていません",
"modelIdEmpty": "モデル ID は空にできません",
"modelIdExists": "このモデル ID は既に存在します",
"configureProviders": "AI プロバイダーの設定",
"selectProviderHint": "リストからプロバイダーを選択するか、新規追加して API キーとモデルを設定",
"deleteConfirmDesc": "{name} を削除してもよろしいですか?設定されたすべてのモデルが削除され、元に戻せません。",
"typeToConfirm": "確認のため「{name}」と入力",
"typeProviderName": "プロバイダー名を入力...",
"modelsConfiguredCount": "{count} 個のモデルを設定済み",
"validationFailedCount": "{count} 個のモデルの検証に失敗",
"requestFailed": "リクエストに失敗しました({status})",
"cancel": "キャンセル",
"delete": "削除",
@@ -366,22 +353,88 @@
"usingServerDefault": "サーバーデフォルトモデルを使用中",
"selectModel": "モデルを選択",
"searchModels": "モデルを検索...",
"noVerifiedModels": "検証済みのモデルがありません。先にモデルをテストしてください。",
"noModelsFound": "モデルが見つかりません。",
"default": "デフォルト",
"serverDefault": "サーバーデフォルト",
"serverModels": "サーバーモデル",
"userModels": "ユーザーモデル",
"configureModels": "モデルを設定...",
"onlyVerifiedShown": "検証済みのモデルのみ表示",
"showUnvalidatedModels": "未検証のモデルを表示",
"allModelsShown": "すべてのモデルを表示(未検証を含む)",
"unvalidatedModelWarning": "このモデルは検証されていません",
"serverDefaultModel": "サーバーデフォルトモデル",
"showValue": "値を表示",
"hideValue": "値を非表示",
"noProvidersTitle": "このサーバーで設定されたモデルを使用中",
"noProvidersHint": "ほかのモデルを使うには、左のリストの下でプロバイダーを追加し、自分の API キーを入力してください。"
"myProviders": "マイプロバイダー",
"inUse": "使用中",
"listSeparator": "、",
"serverModelsTitle": "このサーバーのモデル",
"serverDefaultSummary": "API キーは不要です。サーバーの既定のモデルを使います。",
"statusError": "{count} 個でエラー",
"statusIncomplete": "設定が終わっていません",
"statusUntested": "{count} 個が未テスト",
"statusOk": "{count} 個が使用可能",
"noModelsYet": "モデルはまだありません",
"keysStayLocal": "API キーはこの端末のブラウザーにだけ保存され、リクエストのときだけサーバーに送られます。",
"useOwnKey": "自分の API キーを使う",
"useOwnKeyHint": "プロバイダーを追加すると、チャットのモデル選択でそのモデルを使えます。まず一つ選んでください:",
"viewAllProviders": "{count} 個のプロバイダーをすべて表示",
"searchProviders": "プロバイダーを検索(例:DeepSeek、Qwen、Ollama)",
"noProvidersFound": "一致するプロバイダーはありません。",
"groupVendors": "モデル開発元",
"groupAggregators": "アグリゲーター",
"groupCloud": "クラウド",
"groupSelfHosted": "セルフホスト",
"noteBedrock": "AWS 認証情報",
"noteVertex": "Express モードのキー",
"noteAzure": "キーとリソース URL",
"noteEdgeone": "キー不要",
"noteOllama": "キーは任意",
"noteSglang": "サーバーの URL",
"added": "追加済み",
"awsCredentials": "AWS 認証情報",
"bedrockAuthApiKey": "Bedrock API キー",
"bedrockAuthAccessKey": "アクセスキー",
"moreOptions": "その他のオプション:ベース URL、表示名",
"moreOptionsName": "その他のオプション:表示名",
"keyRejected": "プロバイダーがこの API キーを拒否しました。上のキーが最後までコピーされているか確認してください。",
"modelNotFound": "プロバイダーがこのモデル ID を見つけられません。綴りを確認してください。",
"modelWorks": "使用可能",
"modelWorksTime": "使用可能 · {seconds} 秒",
"modelFailed": "エラー",
"modelUntested": "未テスト",
"needKey": "先に API キーを入力してください。",
"needAws": "先に AWS 認証情報とリージョンを入力してください。",
"needModel": "先にモデルを追加してください。",
"stepConnect": "接続",
"edgeoneNoKey": "EdgeOne Pages はこのサイトのデプロイに付属するモデルサービスを使うため、API キーは不要です。",
"stepModels": "モデル",
"fetchAllModels": "{name} から全モデルを取得",
"suggestedLabel": "おすすめ:",
"orTypeModelId": "または別のモデル ID を入力",
"add": "追加",
"browseModels": "モデル一覧",
"stepTest": "テスト",
"testHint": "各モデルに短いメッセージを送り、キーとモデルが使えるか確認します。",
"testOne": "{model} をテスト",
"testAll": "{count} 個のモデルをすべてテスト",
"testPassedOne": "{model} は使用できます",
"testPassedAll": "{count} 個のモデルすべてが使用できます",
"answeredIn": "(応答 {seconds} 秒)",
"useInChat": "チャットで {model} を使う",
"backToProviders": "プロバイダー一覧に戻る",
"deleteProviderOnly": "{name} を削除",
"addProviderEntry": "プロバイダーを追加…",
"awsKeysRejected": "AWS がこのアクセスキーを拒否しました。2 つとも最後までコピーされているか確認してください。",
"needAzure": "先に API キーと Azure リソースのベース URL を入力してください。",
"validationFailedCountOne": "{count} 個のモデルがテストに失敗しました",
"validationFailedCountOther": "{count} 個のモデルがテストに失敗しました",
"deleteProviderNamedOne": "{name} とそのモデルを削除",
"deleteProviderNamedOther": "{name} と {count} 個のモデルを削除",
"serverModelsSummaryOne": "API キーは不要です。{count} 個:{names}",
"serverModelsSummaryOther": "API キーは不要です。{count} 個:{names}",
"noModelsReturned": "プロバイダーからモデルが返されませんでした。",
"awsSessionToken": "AWS セッショントークン(任意)",
"awsSessionTokenHint": "一時的な認証情報(ASIA で始まるアクセスキー)の場合だけ必要です。",
"bedrockBothSaved": "このプロバイダーにはアクセスキーも保存されていますが、API キーがある間は使われません。",
"removeAccessKeys": "アクセスキーを削除"
},
"templates": {
"emptyTitle": "保存したプロンプトはまだありません",
@@ -612,7 +665,7 @@
"failed": "今回はうまくいきませんでした",
"failedRetrying": "うまくいかなかったので再試行しています",
"stopped": "停止しました",
"truncatedHint": "図が完成する前に出力の上限に達しました。もっと簡単な図を頼むか、設定 > 詳細 で最大出力トークン数を増やしてください。",
"truncatedHint": "図が完成する前に出力の上限に達しました。もっと簡単な図を頼むか、設定 > 描画 で最大出力トークン数を増やしてください。",
"noChanges": "目に見える変更はありません",
"listSeparator": "、",
"shapesAddedOne": "図形を 1 個追加",
+92 -39
View File
@@ -120,9 +120,7 @@
"customSystemMessagePlaceholder": "例如:圖表始終使用藍色配色方案...",
"maxOutputTokens": "最大輸出 token 數",
"maxOutputTokensDescription": "單次回覆的額度,思考過程與圖表 XML 共用。若 AI 一直在思考卻沒有產生圖表,請將它調大。留空則使用預設值。",
"tabModels": "模型與金鑰",
"tabAppearance": "外觀",
"tabAdvanced": "進階",
"tabModels": "模型",
"tabAbout": "關於",
"themeLight": "淺色",
"themeDarkMode": "深色",
@@ -131,7 +129,11 @@
"proxyInvalid": "代理位址必須以 http:// 或 https:// 開頭",
"proxyFailed": "代理設定沒有生效",
"appVersion": "版本",
"projectWebsite": "專案網站"
"projectWebsite": "專案網站",
"tabGeneral": "一般",
"tabDrawing": "繪圖",
"sectionInterface": "介面",
"sectionAccess": "存取"
},
"save": {
"title": "匯出圖紙",
@@ -213,11 +215,11 @@
"messageApiSelfHosted": null,
"messageToken": "看來您今天的 Token 用量已達上限。非常高興您玩得開心,雖然本專案由字節跳動豆包慷慨贊助,但為了確保大家都能公平使用,我們不得不對使用量做一點小小的限制。",
"messageTokenSelfHosted": null,
"tip": "<strong>提示:</strong>您可以使用自己的 API 金鑰(點擊設定圖示)或自行託管專案來繞過這些限制。",
"tipSelfHosted": "<strong>提示:</strong>您可以在設定中配置自己的 API 金鑰以繼續使用服務。",
"tip": "<strong>提示:</strong>您可以使用自己的 API Key(點擊設定圖示)或自行託管專案來繞過這些限制。",
"tipSelfHosted": "<strong>提示:</strong>您可以在設定中配置自己的 API Key 以繼續使用服務。",
"reset": "您的限制將在明天重設。感謝您的理解。",
"doubaoSponsorship": "<a href=\"{link}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"underline hover:text-foreground\">點此註冊</a>可獲得每個模型 50 萬免費 Token(包括豆包、DeepSeek 和 Kimi),然後在模型設定中配置您的 API Key。",
"configModel": "使用您的金鑰",
"configModel": "使用自己的 API Key",
"selfHost": "自行託管",
"sponsor": "贊助",
"learnMore": "了解更多 →",
@@ -351,38 +353,29 @@
},
"modelConfig": {
"configure": "配置",
"addProvider": "新增提供商",
"addProvider": "新增服務商",
"addModel": "新增模型",
"modelId": "模型 ID",
"modelLabel": "顯示名稱",
"streaming": "啟用串流輸出",
"deleteProvider": "刪除提供商",
"deleteProvider": "刪除服務商",
"deleteModel": "刪除模型",
"noModels": "尚未配置模型。新增模型以開始使用。",
"selectProvider": "選擇一個提供商或新增",
"configureMultiple": "配置多個 AI 提供商並輕鬆切換",
"apiKeyStored": "API 金鑰儲存在您的瀏覽器本機",
"test": "測試",
"validationError": "驗證失敗",
"addModelFirst": "請先新增至少一個模型以進行驗證",
"providers": "提供商",
"addProviderHint": "還沒有服務商",
"verified": "已驗證",
"configuration": "配置",
"validationError": "測試沒通過",
"addModelFirst": "先新增一個模型。",
"displayName": "顯示名稱",
"bedrockApiKey": "Bedrock API 金鑰",
"bedrockApiKey": "Bedrock API Key",
"bedrockApiKeyHint": "填了 API 金鑰,下面的存取金鑰就不用填。",
"awsAccessKeyId": "AWS 存取金鑰 ID",
"awsSecretAccessKey": "AWS Secret Access Key",
"awsRegion": "AWS 區域",
"selectRegion": "選擇區域",
"apiKey": "API 金鑰",
"enterApiKey": "輸入您的 API 金鑰",
"enterSecretKey": "輸入您的 Secret Key",
"apiKey": "API Key",
"enterApiKey": "輸入 API Key",
"enterSecretKey": "輸入 Secret Access Key",
"baseUrl": "基礎 URL",
"optional": "(可選)",
"getApiKey": "取得 API Key",
"fetchModels": "從服務商取得模型清單",
"noTools": "不支援工具呼叫",
"mayNotDraw": "models.dev 顯示這個模型不支援工具呼叫,可能無法繪圖。",
"requestUrl": "請求將傳送至 {url}",
@@ -393,17 +386,11 @@
"models": "模型",
"customModelId": "自訂模型 ID...",
"allAdded": "已全部新增",
"suggested": "推薦",
"noModelsConfigured": "尚未配置模型",
"modelIdEmpty": "模型 ID 不能為空",
"modelIdExists": "此模型 ID 已存在",
"configureProviders": "設定 AI 服務商",
"selectProviderHint": "從列表中選擇提供商或新增以配置 API 金鑰和模型",
"deleteConfirmDesc": "確定要刪除 {name} 嗎?這將移除所有配置的模型且無法復原。",
"typeToConfirm": "輸入「{name}」以確認",
"typeProviderName": "輸入提供商名稱...",
"modelsConfiguredCount": "已配置 {count} 個模型",
"validationFailedCount": "{count} 個模型驗證失敗",
"typeProviderName": "輸入服務商名稱...",
"requestFailed": "請求失敗({status})",
"cancel": "取消",
"delete": "刪除",
@@ -411,22 +398,88 @@
"usingServerDefault": "使用伺服器預設模型",
"selectModel": "選擇模型",
"searchModels": "搜尋模型...",
"noVerifiedModels": "沒有已驗證的模型。請先測試您的模型。",
"noModelsFound": "未找到模型。",
"default": "預設",
"serverDefault": "伺服器預設",
"serverModels": "伺服器模型",
"userModels": "使用者模型",
"configureModels": "配置模型...",
"onlyVerifiedShown": "僅顯示已驗證的模型",
"showUnvalidatedModels": "顯示未驗證的模型",
"allModelsShown": "顯示所有模型(包括未驗證的)",
"unvalidatedModelWarning": "此模型尚未驗證",
"serverDefaultModel": "伺服器預設模型",
"showValue": "顯示值",
"hideValue": "隱藏值",
"noProvidersTitle": "正在使用伺服器上設定的模型",
"noProvidersHint": "想用其他模型,可以在左側清單下方新增服務商並填寫自己的 API Key。"
"myProviders": "我的服務商",
"inUse": "正在使用",
"listSeparator": "、",
"serverModelsTitle": "伺服器提供的模型",
"serverDefaultSummary": "不用填寫 API Key,使用伺服器設定的預設模型。",
"statusError": "{count} 個模型出錯",
"statusIncomplete": "還沒設定完",
"statusUntested": "{count} 個模型未測試",
"statusOk": "{count} 個模型可用",
"noModelsYet": "還沒有模型",
"keysStayLocal": "API Key 只儲存在這台裝置的瀏覽器裡,發送請求時才帶給伺服器。",
"useOwnKey": "使用自己的 API Key",
"useOwnKeyHint": "接入其他服務商後,就能在聊天框的模型選擇器裡換用它們的模型。選一個開始:",
"viewAllProviders": "查看全部 {count} 個服務商",
"searchProviders": "搜尋服務商,例如 DeepSeek、Qwen、Ollama",
"noProvidersFound": "沒有找到這個服務商。",
"groupVendors": "模型廠商",
"groupAggregators": "聚合平台",
"groupCloud": "雲端平台",
"groupSelfHosted": "自行部署",
"noteBedrock": "AWS 憑證",
"noteVertex": "Express 模式 Key",
"noteAzure": "Key 和資源位址",
"noteEdgeone": "不用 Key",
"noteOllama": "Key 可不填",
"noteSglang": "填服務位址",
"added": "已新增",
"awsCredentials": "AWS 憑證",
"bedrockAuthApiKey": "Bedrock API Key",
"bedrockAuthAccessKey": "存取金鑰",
"moreOptions": "更多選項:Base URL、顯示名稱",
"moreOptionsName": "更多選項:顯示名稱",
"keyRejected": "服務商拒絕了這個 API Key。檢查上面的 Key 是否複製完整。",
"modelNotFound": "服務商找不到這個模型 ID,請檢查拼寫。",
"modelWorks": "可用",
"modelWorksTime": "可用 · {seconds} 秒",
"modelFailed": "出錯",
"modelUntested": "未測試",
"needKey": "先填好 API Key。",
"needAws": "先填好 AWS 憑證和區域。",
"needModel": "先新增一個模型。",
"stepConnect": "連線",
"edgeoneNoKey": "EdgeOne Pages 使用這個網站部署時內建的模型服務,不用填寫 API Key。",
"stepModels": "選擇模型",
"fetchAllModels": "從 {name} 取得全部模型",
"suggestedLabel": "推薦:",
"orTypeModelId": "或者輸入其他模型 ID",
"add": "新增",
"browseModels": "瀏覽模型",
"stepTest": "測試",
"testHint": "給每個模型發一條很短的訊息,確認 Key 和模型都能用。",
"testOne": "測試 {model}",
"testAll": "測試全部 {count} 個模型",
"testPassedOne": "{model} 可以用了",
"testPassedAll": "{count} 個模型都可以用了",
"answeredIn": "(回覆用了 {seconds} 秒)",
"useInChat": "在聊天裡使用 {model}",
"backToProviders": "返回服務商列表",
"deleteProviderOnly": "刪除 {name}",
"addProviderEntry": "新增服務商…",
"awsKeysRejected": "AWS 拒絕了這組存取金鑰。檢查兩個金鑰是否都複製完整。",
"needAzure": "先填好 API Key 和 Azure 資源的 Base URL。",
"validationFailedCountOne": "{count} 個模型沒通過測試",
"validationFailedCountOther": "{count} 個模型沒通過測試",
"deleteProviderNamedOne": "刪除 {name} 和它的 {count} 個模型",
"deleteProviderNamedOther": "刪除 {name} 和它的 {count} 個模型",
"serverModelsSummaryOne": "不用填寫 API Key。共 {count} 個:{names}",
"serverModelsSummaryOther": "不用填寫 API Key。共 {count} 個:{names}",
"noModelsReturned": "服務商沒有回傳任何模型。",
"awsSessionToken": "AWS Session Token(選填)",
"awsSessionTokenHint": "只有臨時憑證才需要,也就是以 ASIA 開頭的存取金鑰。",
"bedrockBothSaved": "這個服務商還保存著一對存取金鑰,有 API Key 時它們不會被用到。",
"removeAccessKeys": "刪除存取金鑰"
},
"admin": {
"title": "管理員設定",
@@ -612,7 +665,7 @@
"failed": "這次沒有成功",
"failedRetrying": "這次沒有成功,正在重試",
"stopped": "已停止",
"truncatedHint": "回覆達到輸出長度上限,圖表沒有畫完。可以要一張簡單些的圖,或在 設定 > 進階 中調高最大輸出長度。",
"truncatedHint": "回覆達到輸出長度上限,圖表沒有畫完。可以要一張簡單些的圖,或在 設定 > 繪圖 中調高最大輸出長度。",
"noChanges": "沒有可見的變化",
"listSeparator": ",",
"shapesAddedOne": "新增 1 個圖形",
+92 -39
View File
@@ -120,9 +120,7 @@
"customSystemMessagePlaceholder": "例如:图表始终使用蓝色配色方案...",
"maxOutputTokens": "最大输出 token 数",
"maxOutputTokensDescription": "单次回复的额度,思考过程和图表 XML 共用。如果 AI 一直在思考却没有生成图表,请把它调大。留空则使用默认值。",
"tabModels": "模型和密钥",
"tabAppearance": "外观",
"tabAdvanced": "高级",
"tabModels": "模型",
"tabAbout": "关于",
"themeLight": "浅色",
"themeDarkMode": "深色",
@@ -131,7 +129,11 @@
"proxyInvalid": "代理地址必须以 http:// 或 https:// 开头",
"proxyFailed": "代理设置没有生效",
"appVersion": "版本",
"projectWebsite": "项目网站"
"projectWebsite": "项目网站",
"tabGeneral": "通用",
"tabDrawing": "绘图",
"sectionInterface": "界面",
"sectionAccess": "访问"
},
"save": {
"title": "导出图纸",
@@ -213,11 +215,11 @@
"messageApiSelfHosted": null,
"messageToken": "看来您今天的 Token 用量已达上限。非常高兴您玩得开心,虽然本项目由字节跳动豆包慷慨赞助,但为了确保大家都能公平使用,我们不得不对使用量做一点小小的限制。",
"messageTokenSelfHosted": null,
"tip": "<strong>提示:</strong>您可以使用自己的 API 密钥(点击设置图标)或自托管项目来绕过这些限制。",
"tipSelfHosted": "<strong>提示:</strong>您可以在设置中配置自己的 API 密钥以继续使用服务。",
"tip": "<strong>提示:</strong>您可以使用自己的 API Key(点击设置图标)或自托管项目来绕过这些限制。",
"tipSelfHosted": "<strong>提示:</strong>您可以在设置中配置自己的 API Key 以继续使用服务。",
"reset": "您的限制将在明天重置。感谢您的理解。",
"doubaoSponsorship": "<a href=\"{link}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"underline hover:text-foreground\">点击此处注册</a>可获得每个模型 50 万免费 Token(包括豆包、DeepSeek 和 Kimi),然后在模型设置中配置您的 API Key。",
"configModel": "使用您的密钥",
"configModel": "使用自己的 API Key",
"selfHost": "自托管",
"sponsor": "赞助",
"learnMore": "了解更多 →",
@@ -351,38 +353,29 @@
},
"modelConfig": {
"configure": "配置",
"addProvider": "添加提供商",
"addProvider": "添加服务商",
"addModel": "添加模型",
"modelId": "模型 ID",
"modelLabel": "显示名称",
"streaming": "启用流式输出",
"deleteProvider": "删除提供商",
"deleteProvider": "删除服务商",
"deleteModel": "删除模型",
"noModels": "尚未配置模型。添加模型以开始使用。",
"selectProvider": "选择一个提供商或添加新的",
"configureMultiple": "配置多个 AI 提供商并轻松切换",
"apiKeyStored": "API 密钥存储在您的浏览器本地",
"test": "测试",
"validationError": "验证失败",
"addModelFirst": "请先添加至少一个模型以进行验证",
"providers": "提供商",
"addProviderHint": "还没有服务商",
"verified": "已验证",
"configuration": "配置",
"validationError": "测试没通过",
"addModelFirst": "先添加一个模型。",
"displayName": "显示名称",
"bedrockApiKey": "Bedrock API 密钥",
"bedrockApiKey": "Bedrock API Key",
"bedrockApiKeyHint": "填了 API 密钥,下面的访问密钥就不用填。",
"awsAccessKeyId": "AWS 访问密钥 ID",
"awsSecretAccessKey": "AWS Secret Access Key",
"awsRegion": "AWS 区域",
"selectRegion": "选择区域",
"apiKey": "API 密钥",
"enterApiKey": "输入您的 API 密钥",
"enterSecretKey": "输入您的 Secret Key",
"apiKey": "API Key",
"enterApiKey": "输入 API Key",
"enterSecretKey": "输入 Secret Access Key",
"baseUrl": "基础 URL",
"optional": "(可选)",
"getApiKey": "获取 API Key",
"fetchModels": "从服务商获取模型列表",
"noTools": "不支持工具调用",
"mayNotDraw": "models.dev 显示这个模型不支持工具调用,可能无法画图。",
"requestUrl": "请求将发往 {url}",
@@ -393,17 +386,11 @@
"models": "模型",
"customModelId": "自定义模型 ID...",
"allAdded": "已全部添加",
"suggested": "推荐",
"noModelsConfigured": "尚未配置模型",
"modelIdEmpty": "模型 ID 不能为空",
"modelIdExists": "此模型 ID 已存在",
"configureProviders": "设置 AI 服务商",
"selectProviderHint": "从列表中选择提供商或添加新的以配置 API 密钥和模型",
"deleteConfirmDesc": "确定要删除 {name} 吗?这将移除所有配置的模型且无法撤销。",
"typeToConfirm": "输入 \"{name}\" 以确认",
"typeProviderName": "输入提供商名称...",
"modelsConfiguredCount": "已配置 {count} 个模型",
"validationFailedCount": "{count} 个模型验证失败",
"typeProviderName": "输入服务商名称...",
"requestFailed": "请求失败({status})",
"cancel": "取消",
"delete": "删除",
@@ -411,22 +398,88 @@
"usingServerDefault": "使用服务器默认模型",
"selectModel": "选择模型",
"searchModels": "搜索模型...",
"noVerifiedModels": "没有已验证的模型。请先测试您的模型。",
"noModelsFound": "未找到模型。",
"default": "默认",
"serverDefault": "服务器默认",
"serverModels": "服务器模型",
"userModels": "用户模型",
"configureModels": "配置模型...",
"onlyVerifiedShown": "仅显示已验证的模型",
"showUnvalidatedModels": "显示未验证的模型",
"allModelsShown": "显示所有模型(包括未验证的)",
"unvalidatedModelWarning": "此模型尚未验证",
"serverDefaultModel": "服务器默认模型",
"showValue": "显示值",
"hideValue": "隐藏值",
"noProvidersTitle": "正在使用服务器上配置的模型",
"noProvidersHint": "想用其他模型,可以在左侧列表下方添加服务商并填写自己的 API Key。"
"myProviders": "我的服务商",
"inUse": "正在使用",
"listSeparator": "、",
"serverModelsTitle": "服务器提供的模型",
"serverDefaultSummary": "不用填写 API Key,使用服务器配置的默认模型。",
"statusError": "{count} 个模型出错",
"statusIncomplete": "还没设置完",
"statusUntested": "{count} 个模型未测试",
"statusOk": "{count} 个模型可用",
"noModelsYet": "还没有模型",
"keysStayLocal": "API Key 只保存在这台设备的浏览器里,发请求时才带给服务器。",
"useOwnKey": "用自己的 API Key",
"useOwnKeyHint": "接入其他服务商后,就能在聊天框的模型选择器里换用它们的模型。选一个开始:",
"viewAllProviders": "查看全部 {count} 个服务商",
"searchProviders": "搜索服务商,比如 DeepSeek、Qwen、Ollama",
"noProvidersFound": "没有找到这个服务商。",
"groupVendors": "模型厂商",
"groupAggregators": "聚合平台",
"groupCloud": "云平台",
"groupSelfHosted": "自己部署",
"noteBedrock": "AWS 凭证",
"noteVertex": "Express 模式 Key",
"noteAzure": "Key 和资源地址",
"noteEdgeone": "不用 Key",
"noteOllama": "Key 可不填",
"noteSglang": "填服务地址",
"added": "已添加",
"awsCredentials": "AWS 凭证",
"bedrockAuthApiKey": "Bedrock API Key",
"bedrockAuthAccessKey": "访问密钥",
"moreOptions": "更多选项:Base URL、显示名称",
"moreOptionsName": "更多选项:显示名称",
"keyRejected": "服务商拒绝了这个 API Key。检查上面的 Key 是否复制完整。",
"modelNotFound": "服务商找不到这个模型 ID,请检查拼写。",
"modelWorks": "可用",
"modelWorksTime": "可用 · {seconds} 秒",
"modelFailed": "出错",
"modelUntested": "未测试",
"needKey": "先填好 API Key。",
"needAws": "先填好 AWS 凭证和区域。",
"needModel": "先添加一个模型。",
"stepConnect": "连接",
"edgeoneNoKey": "EdgeOne Pages 使用这个网站部署时自带的模型服务,不用填写 API Key。",
"stepModels": "选择模型",
"fetchAllModels": "从 {name} 获取全部模型",
"suggestedLabel": "推荐:",
"orTypeModelId": "或者输入其他模型 ID",
"add": "添加",
"browseModels": "浏览模型",
"stepTest": "测试",
"testHint": "给每个模型发一条很短的消息,确认 Key 和模型都能用。",
"testOne": "测试 {model}",
"testAll": "测试全部 {count} 个模型",
"testPassedOne": "{model} 可以用了",
"testPassedAll": "{count} 个模型都可以用了",
"answeredIn": "(回复用了 {seconds} 秒)",
"useInChat": "在聊天里使用 {model}",
"backToProviders": "返回服务商列表",
"deleteProviderOnly": "删除 {name}",
"addProviderEntry": "添加服务商…",
"awsKeysRejected": "AWS 拒绝了这组访问密钥。检查两个密钥是否都复制完整。",
"needAzure": "先填好 API Key 和 Azure 资源的 Base URL。",
"validationFailedCountOne": "{count} 个模型没通过测试",
"validationFailedCountOther": "{count} 个模型没通过测试",
"deleteProviderNamedOne": "删除 {name} 和它的 {count} 个模型",
"deleteProviderNamedOther": "删除 {name} 和它的 {count} 个模型",
"serverModelsSummaryOne": "不用填写 API Key。共 {count} 个:{names}",
"serverModelsSummaryOther": "不用填写 API Key。共 {count} 个:{names}",
"noModelsReturned": "服务商没有返回任何模型。",
"awsSessionToken": "AWS Session Token(可选)",
"awsSessionTokenHint": "只有临时凭证才需要,也就是以 ASIA 开头的访问密钥。",
"bedrockBothSaved": "这个服务商还保存着一对访问密钥,有 API Key 时它们不会被用到。",
"removeAccessKeys": "删除访问密钥"
},
"admin": {
"title": "管理员设置",
@@ -612,7 +665,7 @@
"failed": "这次没有成功",
"failedRetrying": "这次没有成功,正在重试",
"stopped": "已停止",
"truncatedHint": "回复达到了输出长度上限,图表没有画完。可以要一张简单些的图,或者在 设置 > 高级 里调高最大输出长度。",
"truncatedHint": "回复达到了输出长度上限,图表没有画完。可以要一张简单些的图,或者在 设置 > 绘图 里调高最大输出长度。",
"noChanges": "没有可见的变化",
"listSeparator": ",",
"shapesAddedOne": "新增 1 个图形",
+138
View File
@@ -0,0 +1,138 @@
// What the model settings show about providers: the groups of the provider
// picker, and how far a provider's setup has come
import {
PROVIDER_INFO,
type ProviderConfig,
type ProviderName,
} from "@/lib/types/model-config"
export type ProviderGroupId = "vendors" | "aggregators" | "cloud" | "selfHosted"
/** The provider picker's groups, each provider in exactly one */
export const PROVIDER_GROUPS: {
id: ProviderGroupId
providers: ProviderName[]
}[] = [
{
id: "vendors",
providers: [
"openai",
"anthropic",
"google",
"deepseek",
"qwen",
"doubao",
"glm",
"kimi",
"minimax",
"mimo",
],
},
{
id: "aggregators",
providers: [
"openrouter",
"aihubmix",
"siliconflow",
"modelscope",
"novita",
"atlascloud",
"qiniu",
"gateway",
],
},
{ id: "cloud", providers: ["bedrock", "vertexai", "azure", "edgeone"] },
{ id: "selfHosted", providers: ["ollama", "sglang"] },
]
/** Shown when the user has no provider yet */
export const POPULAR_PROVIDERS: ProviderName[] = [
"openai",
"anthropic",
"google",
"deepseek",
"openrouter",
"qwen",
]
/** Providers that need something other than a plain API key */
export const PROVIDER_NOTE_KEYS: Partial<Record<ProviderName, string>> = {
bedrock: "noteBedrock",
vertexai: "noteVertex",
azure: "noteAzure",
edgeone: "noteEdgeone",
ollama: "noteOllama",
sglang: "noteSglang",
}
/**
* Providers whose base URL usually needs changing (Azure's default is only
* an example; Ollama's is its cloud, SGLang's a local server) or comes with
* a hint (MiniMax, MiMo): their folded options start open
*/
export const OPTIONS_OPEN: ProviderName[] = [
"azure",
"ollama",
"sglang",
"minimax",
"mimo",
]
/** The groups with only the providers whose name matches the search */
export function filterProviderGroups(query: string) {
const q = query.trim().toLowerCase()
if (!q) return PROVIDER_GROUPS
return PROVIDER_GROUPS.map((group) => ({
...group,
providers: group.providers.filter(
(p) =>
PROVIDER_INFO[p].label.toLowerCase().includes(q) ||
p.includes(q),
),
})).filter((group) => group.providers.length > 0)
}
/** The credentials a test or a chat request needs are filled in */
export function hasCredentials(p: ProviderConfig): boolean {
switch (p.provider) {
case "bedrock":
return (
(!!p.apiKey ||
(!!p.awsAccessKeyId && !!p.awsSecretAccessKey)) &&
!!p.awsRegion
)
case "vertexai":
return !!p.vertexApiKey
// Its default base URL names no real resource
case "azure":
return (
!!p.apiKey &&
!!p.baseUrl &&
p.baseUrl !== PROVIDER_INFO.azure.defaultBaseUrl
)
case "edgeone":
case "ollama":
return true
default:
return !!p.apiKey
}
}
export type ProviderStatus =
| { kind: "error"; count: number }
| { kind: "incomplete" }
| { kind: "untested"; count: number }
| { kind: "ok"; count: number }
/** The one thing about a provider that most needs the user's attention */
export function providerStatus(p: ProviderConfig): ProviderStatus {
const failed = p.models.filter((m) => m.validated === false).length
if (failed > 0) return { kind: "error", count: failed }
if (!hasCredentials(p) || p.models.length === 0) {
return { kind: "incomplete" }
}
const untested = p.models.filter((m) => m.validated !== true).length
if (untested > 0) return { kind: "untested", count: untested }
return { kind: "ok", count: p.models.length }
}
+3 -1
View File
@@ -60,7 +60,9 @@ export interface MultiModelConfig {
version: 1
providers: ProviderConfig[]
selectedModelId?: string // Currently selected model's UUID
showUnvalidatedModels?: boolean // Show models that haven't been validated
// Older versions saved here whether untested models were listed in the
// model picker; they always are now
showUnvalidatedModels?: boolean
}
// Flattened model for dropdown display