update model settings multi lang.

This commit is contained in:
duanfuxiang 2025-06-12 15:19:07 +08:00
parent b20b4f9e19
commit 6501132d80
7 changed files with 63 additions and 22 deletions

View File

@ -56,7 +56,6 @@ export const getEmbeddingModel = (
}
},
getBatchEmbeddings: async (texts: string[]) => {
console.log("use getBatchEmbeddings", texts.length)
try {
if (!openai.apiKey) {
throw new LLMAPIKeyNotSetException(

View File

@ -56,7 +56,7 @@ const localeMap: { [k: string]: Partial<typeof en> } = {
const locale = localeMap[moment.locale()];
export function t(str: string): any {
export function t(str: string, params?: Record<string, any>): any {
if (!locale) {
console.error({
plugin: "infio-copilot",
@ -75,5 +75,12 @@ export function t(str: string): any {
if (result === undefined) return str;
}
// Handle parameter interpolation
if (params && typeof result === 'string') {
return result.replace(/\{([^}]+)\}/g, (match, key) => {
return params[key] !== undefined ? String(params[key]) : match;
});
}
return result;
}

View File

@ -216,8 +216,29 @@ export default {
},
Models: {
chatModel: 'Chat model:',
chatModelDescription: 'Model used for daily conversations and Q&A, handling most chat interactions',
autocompleteModel: 'Autocomplete model:',
autocompleteModelDescription: 'Model used for code and text autocompletion, providing intelligent writing suggestions',
embeddingModel: 'Embedding model:',
embeddingModelDescription: 'Model used for document vectorization and semantic search, supporting RAG functionality',
},
// Model Provider Settings
ModelProvider: {
noApiKeySet: 'No API key has been set',
setApiKey: 'Set {provider} API Key',
modelSelection: 'Model Selection',
oneClickConfig: 'One-Click Config',
oneClickConfigTooltip: 'Automatically configure models to recommended models from providers with API keys set',
chatModelConfigured: 'Chat model configured automatically: {provider}/{model}',
autocompleteModelConfigured: 'Autocomplete model configured automatically: {provider}/{model}',
embeddingModelConfigured: 'Embedding model configured automatically: {provider}/{model}',
provider: 'Provider',
model: 'Model',
selectModel: 'Select model...',
searchOrEnterModelName: 'Search or enter model name...',
enterCustomModelName: 'Enter custom model name',
custom: 'Custom: ',
},
// Model Parameters Section

View File

@ -224,6 +224,24 @@ export default {
embeddingModelDescription: '用于文档向量化和语义搜索的模型,支持 RAG 功能',
},
// 模型提供商设置
ModelProvider: {
noApiKeySet: '当前未设置任何 API Key',
setApiKey: '设置 {provider} API Key',
modelSelection: '模型选择',
oneClickConfig: '一键配置',
oneClickConfigTooltip: '自动配置模型为已设置 API Key 的提供商的推荐模型',
chatModelConfigured: '已自动配置聊天模型:{provider}/{model}',
autocompleteModelConfigured: '已自动配置自动补全模型:{provider}/{model}',
embeddingModelConfigured: '已自动配置嵌入模型:{provider}/{model}',
provider: '提供商',
model: '模型',
selectModel: '选择模型...',
searchOrEnterModelName: '搜索或输入模型名称...',
enterCustomModelName: '输入自定义模型名称',
custom: '自定义: ',
},
// 模型参数部分
ModelParameters: {
title: '模型参数',

View File

@ -82,7 +82,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
if (settedProviders.length === 0) {
// 提示用户未设置任何key
alert("当前未设置任何key");
alert(t("settings.ModelProvider.noApiKeySet"));
return;
}
@ -104,13 +104,13 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
newSettings.chatModelProvider = selectedProvider;
newSettings.chatModelId = defaultModels.chat;
hasUpdates = true;
console.log(`已自动配置聊天模型:${selectedProvider}/${defaultModels.chat}`);
console.log(t("settings.ModelProvider.chatModelConfigured", { provider: selectedProvider, model: defaultModels.chat }));
}
if (defaultModels.autoComplete) {
newSettings.applyModelProvider = selectedProvider;
newSettings.applyModelId = defaultModels.autoComplete;
hasUpdates = true;
console.log(`已自动配置自动补全模型:${selectedProvider}/${defaultModels.autoComplete}`);
console.log(t("settings.ModelProvider.autocompleteModelConfigured", { provider: selectedProvider, model: defaultModels.autoComplete }));
}
}
@ -122,7 +122,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
newSettings.embeddingModelProvider = embeddingProvider;
newSettings.embeddingModelId = embeddingDefaultModels.embedding;
hasUpdates = true;
console.log(`已自动配置嵌入模型:${embeddingProvider}/${embeddingDefaultModels.embedding}`);
console.log(t("settings.ModelProvider.embeddingModelConfigured", { provider: embeddingProvider, model: embeddingDefaultModels.embedding }));
}
}
@ -217,7 +217,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
// 生成包含链接的API Key描述
const generateApiKeyDescription = (provider: ApiProvider): React.ReactNode => {
const apiUrl = getProviderApiUrl(provider);
const baseDescription = t("settings.ApiProvider.enterApiKeyDescription");
const baseDescription = String(t("settings.ApiProvider.enterApiKeyDescription"));
if (!apiUrl) {
// 如果没有URL直接移除占位符
@ -253,11 +253,7 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
<div className="provider-config">
{provider !== ApiProvider.Ollama && (
<ApiKeyComponent
name={
<>
<span className="provider-name-highlight">{provider}</span> API Key
</>
}
name={t("settings.ModelProvider.setApiKey", { provider })}
placeholder={t("settings.ApiProvider.enterApiKey")}
description={generateApiKeyDescription(provider)}
value={providerSetting.apiKey || ''}
@ -306,13 +302,13 @@ const CustomProviderSettings: React.FC<CustomProviderSettingsProps> = ({ plugin,
{/* 模型选择区域 */}
<div className="model-selection-section">
<div className="model-selection-header">
<h2 className="section-title"></h2>
<h2 className="section-title">{t("settings.ModelProvider.modelSelection")}</h2>
<button
className="one-click-config-btn"
onClick={handleOneClickConfig}
title="自动配置模型为已设置API Key的提供商的推荐模型"
title={t("settings.ModelProvider.oneClickConfigTooltip")}
>
{t("settings.ModelProvider.oneClickConfig")}
</button>
</div>

View File

@ -2,6 +2,7 @@ import * as Popover from "@radix-ui/react-popover";
import Fuse, { FuseResult } from "fuse.js";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { t } from "../../lang/helpers";
import { ApiProvider } from "../../types/llm/model";
import { InfioSettings } from "../../types/settings";
// import { PROVIDERS } from '../constants';
@ -224,7 +225,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
if (!exactMatch) {
results.unshift({
id: searchTerm,
html: [{ text: `${modelIds.length > 0 ? '自定义: ' : ''}${searchTerm}`, isHighlighted: false }]
html: [{ text: `${modelIds.length > 0 ? t("settings.ModelProvider.custom") : ''}${searchTerm}`, isHighlighted: false }]
});
}
}
@ -268,7 +269,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
<div className="infio-llm-setting-item-content">
{/* Provider Selection - Now visible outside */}
<div className="infio-llm-setting-provider-container">
<label className="infio-llm-setting-provider-label"></label>
<label className="infio-llm-setting-provider-label">{t("settings.ModelProvider.provider")}</label>
<select
className="dropdown infio-llm-setting-provider-select"
value={modelProvider}
@ -287,12 +288,12 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
{/* Model Selection */}
<div className="infio-llm-setting-model-container">
<label className="infio-llm-setting-model-label"></label>
<label className="infio-llm-setting-model-label">{t("settings.ModelProvider.model")}</label>
<Popover.Root modal={false} open={isOpen} onOpenChange={setIsOpen}>
<Popover.Trigger asChild>
<button className="infio-llm-setting-model-trigger clickable-icon" type="button">
<span className="infio-llm-setting-model-display">
{modelId || "选择模型..."}
{modelId || t("settings.ModelProvider.selectModel")}
</span>
<svg
className="infio-llm-setting-model-arrow"
@ -322,7 +323,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
<input
type="text"
className="infio-llm-setting-item-search"
placeholder={modelIds.length > 0 ? "搜索或输入模型名称..." : "输入自定义模型名称"}
placeholder={modelIds.length > 0 ? t("settings.ModelProvider.searchOrEnterModelName") : t("settings.ModelProvider.enterCustomModelName")}
value={searchTerm}
onChange={(e) => {
setSearchTerm(e.target.value);
@ -348,7 +349,7 @@ export const ComboBoxComponent: React.FC<ComboBoxComponentProps> = ({
updateModel(modelProvider, selectedOption.id);
}
} else if (searchTerm.trim()) {
// 如果没有选项但有输入内容,直接使用输入内容
// If no options but there is input content, use the input content directly
updateModel(modelProvider, searchTerm.trim());
}
setSearchTerm("");

View File

@ -147,7 +147,6 @@ export const infioDefaultModelInfo: ModelInfo = {
let infioModelsCache: Record<string, ModelInfo> | null = null;
async function fetchInfioModels(apiKey?: string): Promise<Record<string, ModelInfo>> {
console.log("fetchInfioModels apiKey", apiKey)
if (infioModelsCache) {
return infioModelsCache;
}