Update translations and add language settings
This commit is contained in:
66
lightrag_webui/src/components/AppSettings.tsx
Normal file
66
lightrag_webui/src/components/AppSettings.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { useState, useCallback } from 'react'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
|
||||||
|
import Button from '@/components/ui/Button'
|
||||||
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/Select'
|
||||||
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
|
import { PaletteIcon } from 'lucide-react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
export default function AppSettings() {
|
||||||
|
const [opened, setOpened] = useState<boolean>(false)
|
||||||
|
const { t } = useTranslation()
|
||||||
|
|
||||||
|
const language = useSettingsStore.use.language()
|
||||||
|
const setLanguage = useSettingsStore.use.setLanguage()
|
||||||
|
|
||||||
|
const theme = useSettingsStore.use.theme()
|
||||||
|
const setTheme = useSettingsStore.use.setTheme()
|
||||||
|
|
||||||
|
const handleLanguageChange = useCallback((value: string) => {
|
||||||
|
setLanguage(value as 'en' | 'zh')
|
||||||
|
}, [setLanguage])
|
||||||
|
|
||||||
|
const handleThemeChange = useCallback((value: string) => {
|
||||||
|
setTheme(value as 'light' | 'dark' | 'system')
|
||||||
|
}, [setTheme])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover open={opened} onOpenChange={setOpened}>
|
||||||
|
<PopoverTrigger asChild>
|
||||||
|
<Button variant="outline" size="icon" className="h-9 w-9">
|
||||||
|
<PaletteIcon className="h-5 w-5" />
|
||||||
|
</Button>
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent side="bottom" align="end" className="w-56">
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<label className="text-sm font-medium">{t('settings.language')}</label>
|
||||||
|
<Select value={language} onValueChange={handleLanguageChange}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="en">English</SelectItem>
|
||||||
|
<SelectItem value="zh">中文</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<label className="text-sm font-medium">{t('settings.theme')}</label>
|
||||||
|
<Select value={theme} onValueChange={handleThemeChange}>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="light">{t('settings.light')}</SelectItem>
|
||||||
|
<SelectItem value="dark">{t('settings.dark')}</SelectItem>
|
||||||
|
<SelectItem value="system">{t('settings.system')}</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { createContext, useEffect, useState } from 'react'
|
import { createContext, useEffect } from 'react'
|
||||||
import { Theme, useSettingsStore } from '@/stores/settings'
|
import { Theme, useSettingsStore } from '@/stores/settings'
|
||||||
|
|
||||||
type ThemeProviderProps = {
|
type ThemeProviderProps = {
|
||||||
@@ -21,30 +21,32 @@ const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
|
|||||||
* Component that provides the theme state and setter function to its children.
|
* Component that provides the theme state and setter function to its children.
|
||||||
*/
|
*/
|
||||||
export default function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
export default function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||||
const [theme, setTheme] = useState<Theme>(useSettingsStore.getState().theme)
|
const theme = useSettingsStore.use.theme()
|
||||||
|
const setTheme = useSettingsStore.use.setTheme()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const root = window.document.documentElement
|
const root = window.document.documentElement
|
||||||
root.classList.remove('light', 'dark')
|
root.classList.remove('light', 'dark')
|
||||||
|
|
||||||
if (theme === 'system') {
|
if (theme === 'system') {
|
||||||
const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||||
? 'dark'
|
const handleChange = (e: MediaQueryListEvent) => {
|
||||||
: 'light'
|
root.classList.remove('light', 'dark')
|
||||||
root.classList.add(systemTheme)
|
root.classList.add(e.matches ? 'dark' : 'light')
|
||||||
setTheme(systemTheme)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root.classList.add(mediaQuery.matches ? 'dark' : 'light')
|
||||||
|
mediaQuery.addEventListener('change', handleChange)
|
||||||
|
|
||||||
|
return () => mediaQuery.removeEventListener('change', handleChange)
|
||||||
|
} else {
|
||||||
root.classList.add(theme)
|
root.classList.add(theme)
|
||||||
|
}
|
||||||
}, [theme])
|
}, [theme])
|
||||||
|
|
||||||
const value = {
|
const value = {
|
||||||
theme,
|
theme,
|
||||||
setTheme: (theme: Theme) => {
|
setTheme
|
||||||
useSettingsStore.getState().setTheme(theme)
|
|
||||||
setTheme(theme)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import Button from '@/components/ui/Button'
|
import Button from '@/components/ui/Button'
|
||||||
import { SiteInfo } from '@/lib/constants'
|
import { SiteInfo } from '@/lib/constants'
|
||||||
import ThemeToggle from '@/components/ThemeToggle'
|
import AppSettings from '@/components/AppSettings'
|
||||||
import { TabsList, TabsTrigger } from '@/components/ui/Tabs'
|
import { TabsList, TabsTrigger } from '@/components/ui/Tabs'
|
||||||
import { useSettingsStore } from '@/stores/settings'
|
import { useSettingsStore } from '@/stores/settings'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
@@ -67,12 +67,14 @@ export default function SiteHeader() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="flex items-center">
|
<nav className="flex items-center">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
<Button variant="ghost" size="icon" side="bottom" tooltip={t('header.projectRepository')}>
|
<Button variant="ghost" size="icon" side="bottom" tooltip={t('header.projectRepository')}>
|
||||||
<a href={SiteInfo.github} target="_blank" rel="noopener noreferrer">
|
<a href={SiteInfo.github} target="_blank" rel="noopener noreferrer">
|
||||||
<GithubIcon className="size-4" aria-hidden="true" />
|
<GithubIcon className="size-4" aria-hidden="true" />
|
||||||
</a>
|
</a>
|
||||||
</Button>
|
</Button>
|
||||||
<ThemeToggle />
|
<AppSettings />
|
||||||
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import i18n from "i18next";
|
import i18n from 'i18next';
|
||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from 'react-i18next';
|
||||||
|
|
||||||
import en from "./locales/en.json";
|
import en from './locales/en.json';
|
||||||
import zh from "./locales/zh.json";
|
import zh from './locales/zh.json';
|
||||||
|
|
||||||
i18n
|
i18n
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
@@ -11,8 +11,8 @@ i18n
|
|||||||
en: { translation: en },
|
en: { translation: en },
|
||||||
zh: { translation: zh }
|
zh: { translation: zh }
|
||||||
},
|
},
|
||||||
lng: "en", // default
|
lng: 'zh', // default
|
||||||
fallbackLng: "en",
|
fallbackLng: 'zh',
|
||||||
interpolation: {
|
interpolation: {
|
||||||
escapeValue: false
|
escapeValue: false
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"settings": {
|
||||||
|
"language": "Language",
|
||||||
|
"theme": "Theme",
|
||||||
|
"light": "Light",
|
||||||
|
"dark": "Dark",
|
||||||
|
"system": "System"
|
||||||
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"documents": "Documents",
|
"documents": "Documents",
|
||||||
"knowledgeGraph": "Knowledge Graph",
|
"knowledgeGraph": "Knowledge Graph",
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
"settings": {
|
||||||
|
"language": "语言",
|
||||||
|
"theme": "主题",
|
||||||
|
"light": "浅色",
|
||||||
|
"dark": "深色",
|
||||||
|
"system": "系统"
|
||||||
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"documents": "文档",
|
"documents": "文档",
|
||||||
"knowledgeGraph": "知识图谱",
|
"knowledgeGraph": "知识图谱",
|
||||||
@@ -6,41 +13,41 @@
|
|||||||
"api": "API",
|
"api": "API",
|
||||||
"projectRepository": "项目仓库",
|
"projectRepository": "项目仓库",
|
||||||
"themeToggle": {
|
"themeToggle": {
|
||||||
"switchToLight": "切换到亮色主题",
|
"switchToLight": "切换到浅色主题",
|
||||||
"switchToDark": "切换到暗色主题"
|
"switchToDark": "切换到深色主题"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"documentPanel": {
|
"documentPanel": {
|
||||||
"clearDocuments": {
|
"clearDocuments": {
|
||||||
"button": "清除",
|
"button": "清空",
|
||||||
"tooltip": "清除文档",
|
"tooltip": "清空文档",
|
||||||
"title": "清除文档",
|
"title": "清空文档",
|
||||||
"confirm": "您确定要清除所有文档吗?",
|
"confirm": "确定要清空所有文档吗?",
|
||||||
"confirmButton": "确定",
|
"confirmButton": "确定",
|
||||||
"success": "文档已成功清除",
|
"success": "文档清空成功",
|
||||||
"failed": "清除文档失败:\n{{message}}",
|
"failed": "清空文档失败:\n{{message}}",
|
||||||
"error": "清除文档失败:\n{{error}}"
|
"error": "清空文档失败:\n{{error}}"
|
||||||
},
|
},
|
||||||
"uploadDocuments": {
|
"uploadDocuments": {
|
||||||
"button": "上传",
|
"button": "上传",
|
||||||
"tooltip": "上传文档",
|
"tooltip": "上传文档",
|
||||||
"title": "上传文档",
|
"title": "上传文档",
|
||||||
"description": "拖放文档到此处或点击浏览。",
|
"description": "拖拽文件到此处或点击浏览",
|
||||||
"uploading": "正在上传 {{name}}: {{percent}}%",
|
"uploading": "正在上传 {{name}}:{{percent}}%",
|
||||||
"success": "上传成功:\n{{name}} 上传成功",
|
"success": "上传成功:\n{{name}} 上传完成",
|
||||||
"failed": "上传失败:\n{{name}}\n{{message}}",
|
"failed": "上传失败:\n{{name}}\n{{message}}",
|
||||||
"error": "上传失败:\n{{name}}\n{{error}}",
|
"error": "上传失败:\n{{name}}\n{{error}}",
|
||||||
"generalError": "上传失败\n{{error}}",
|
"generalError": "上传失败\n{{error}}",
|
||||||
"fileTypes": "支持的文件类型: TXT, MD, DOCX, PDF, PPTX, RTF, ODT, EPUB, HTML, HTM, TEX, JSON, XML, YAML, YML, CSV, LOG, CONF, INI, PROPERTIES, SQL, BAT, SH, C, CPP, PY, JAVA, JS, TS, SWIFT, GO, RB, PHP, CSS, SCSS, LESS"
|
"fileTypes": "支持的文件类型:TXT, MD, DOCX, PDF, PPTX, RTF, ODT, EPUB, HTML, HTM, TEX, JSON, XML, YAML, YML, CSV, LOG, CONF, INI, PROPERTIES, SQL, BAT, SH, C, CPP, PY, JAVA, JS, TS, SWIFT, GO, RB, PHP, CSS, SCSS, LESS"
|
||||||
},
|
},
|
||||||
"documentManager": {
|
"documentManager": {
|
||||||
"title": "文档管理",
|
"title": "文档管理",
|
||||||
"scanButton": "扫描",
|
"scanButton": "扫描",
|
||||||
"scanTooltip": "扫描文档",
|
"scanTooltip": "扫描文档",
|
||||||
"uploadedTitle": "已上传文档",
|
"uploadedTitle": "已上传文档",
|
||||||
"uploadedDescription": "已上传文档及其状态列表。",
|
"uploadedDescription": "已上传文档列表及其状态",
|
||||||
"emptyTitle": "暂无文档",
|
"emptyTitle": "无文档",
|
||||||
"emptyDescription": "尚未上传任何文档。",
|
"emptyDescription": "还没有上传任何文档",
|
||||||
"columns": {
|
"columns": {
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"summary": "摘要",
|
"summary": "摘要",
|
||||||
@@ -54,7 +61,7 @@
|
|||||||
"status": {
|
"status": {
|
||||||
"completed": "已完成",
|
"completed": "已完成",
|
||||||
"processing": "处理中",
|
"processing": "处理中",
|
||||||
"pending": "待处理",
|
"pending": "等待中",
|
||||||
"failed": "失败"
|
"failed": "失败"
|
||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
@@ -74,40 +81,37 @@
|
|||||||
"showNodeLabel": "显示节点标签",
|
"showNodeLabel": "显示节点标签",
|
||||||
"nodeDraggable": "节点可拖动",
|
"nodeDraggable": "节点可拖动",
|
||||||
"showEdgeLabel": "显示边标签",
|
"showEdgeLabel": "显示边标签",
|
||||||
"hideUnselectedEdges": "隐藏未选中边",
|
"hideUnselectedEdges": "隐藏未选中的边",
|
||||||
"edgeEvents": "边事件",
|
"edgeEvents": "边事件",
|
||||||
"maxQueryDepth": "最大查询深度",
|
"maxQueryDepth": "最大查询深度",
|
||||||
"minDegree": "最小度数",
|
"minDegree": "最小度数",
|
||||||
"maxLayoutIterations": "最大布局迭代次数",
|
"maxLayoutIterations": "最大布局迭代次数",
|
||||||
"apiKey": "API 密钥",
|
"apiKey": "API密钥",
|
||||||
"enterYourAPIkey": "输入您的 API 密钥",
|
"enterYourAPIkey": "输入您的API密钥",
|
||||||
"save": "保存",
|
"save": "保存",
|
||||||
"refreshLayout": "刷新布局"
|
"refreshLayout": "刷新布局"
|
||||||
},
|
},
|
||||||
|
|
||||||
"zoomControl": {
|
"zoomControl": {
|
||||||
"zoomIn": "放大",
|
"zoomIn": "放大",
|
||||||
"zoomOut": "缩小",
|
"zoomOut": "缩小",
|
||||||
"resetZoom": "重置缩放"
|
"resetZoom": "重置缩放"
|
||||||
},
|
},
|
||||||
|
|
||||||
"layoutsControl": {
|
"layoutsControl": {
|
||||||
"startAnimation": "开始布局动画",
|
"startAnimation": "开始布局动画",
|
||||||
"stopAnimation": "停止布局动画",
|
"stopAnimation": "停止布局动画",
|
||||||
"layoutGraph": "布局图",
|
"layoutGraph": "图布局",
|
||||||
"layouts": {
|
"layouts": {
|
||||||
"Circular": "环形布局",
|
"Circular": "环形",
|
||||||
"Circlepack": "圆形打包布局",
|
"Circlepack": "圆形打包",
|
||||||
"Random": "随机布局",
|
"Random": "随机",
|
||||||
"Noverlaps": "无重叠布局",
|
"Noverlaps": "无重叠",
|
||||||
"Force Directed": "力导向布局",
|
"Force Directed": "力导向",
|
||||||
"Force Atlas": "力导向图谱布局"
|
"Force Atlas": "力图"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"fullScreenControl": {
|
"fullScreenControl": {
|
||||||
"fullScreen": "全屏",
|
"fullScreen": "全屏",
|
||||||
"windowed": "窗口模式"
|
"windowed": "窗口"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"statusIndicator": {
|
"statusIndicator": {
|
||||||
@@ -119,17 +123,17 @@
|
|||||||
"storageInfo": "存储信息",
|
"storageInfo": "存储信息",
|
||||||
"workingDirectory": "工作目录",
|
"workingDirectory": "工作目录",
|
||||||
"inputDirectory": "输入目录",
|
"inputDirectory": "输入目录",
|
||||||
"llmConfig": "LLM 配置",
|
"llmConfig": "LLM配置",
|
||||||
"llmBinding": "LLM 绑定",
|
"llmBinding": "LLM绑定",
|
||||||
"llmBindingHost": "LLM 绑定主机",
|
"llmBindingHost": "LLM绑定主机",
|
||||||
"llmModel": "LLM 模型",
|
"llmModel": "LLM模型",
|
||||||
"maxTokens": "最大 Token 数",
|
"maxTokens": "最大令牌数",
|
||||||
"embeddingConfig": "嵌入配置",
|
"embeddingConfig": "嵌入配置",
|
||||||
"embeddingBinding": "嵌入绑定",
|
"embeddingBinding": "嵌入绑定",
|
||||||
"embeddingBindingHost": "嵌入绑定主机",
|
"embeddingBindingHost": "嵌入绑定主机",
|
||||||
"embeddingModel": "嵌入模型",
|
"embeddingModel": "嵌入模型",
|
||||||
"storageConfig": "存储配置",
|
"storageConfig": "存储配置",
|
||||||
"kvStorage": "KV 存储",
|
"kvStorage": "KV存储",
|
||||||
"docStatusStorage": "文档状态存储",
|
"docStatusStorage": "文档状态存储",
|
||||||
"graphStorage": "图存储",
|
"graphStorage": "图存储",
|
||||||
"vectorStorage": "向量存储"
|
"vectorStorage": "向量存储"
|
||||||
@@ -147,90 +151,77 @@
|
|||||||
"title": "关系",
|
"title": "关系",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"type": "类型",
|
"type": "类型",
|
||||||
"source": "源",
|
"source": "源节点",
|
||||||
"target": "目标",
|
"target": "目标节点",
|
||||||
"properties": "属性"
|
"properties": "属性"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "搜索节点...",
|
"placeholder": "搜索节点...",
|
||||||
"message": "以及其它 {count} 项"
|
"message": "还有 {count} 个"
|
||||||
},
|
},
|
||||||
"graphLabels": {
|
"graphLabels": {
|
||||||
"selectTooltip": "选择查询标签",
|
"selectTooltip": "选择查询标签",
|
||||||
"noLabels": "未找到标签",
|
"noLabels": "未找到标签",
|
||||||
"label": "标签",
|
"label": "标签",
|
||||||
"placeholder": "搜索标签...",
|
"placeholder": "搜索标签...",
|
||||||
"andOthers": "以及其它 {count} 个"
|
"andOthers": "还有 {count} 个"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"retrievePanel": {
|
"retrievePanel": {
|
||||||
"chatMessage": {
|
"chatMessage": {
|
||||||
"copyTooltip": "复制到剪贴板",
|
"copyTooltip": "复制到剪贴板",
|
||||||
"copyError": "无法复制文本到剪贴板"
|
"copyError": "复制文本到剪贴板失败"
|
||||||
},
|
},
|
||||||
|
|
||||||
"retrieval": {
|
"retrieval": {
|
||||||
"startPrompt": "在下面输入您的查询以开始检索",
|
"startPrompt": "输入查询开始检索",
|
||||||
"clear": "清除",
|
"clear": "清空",
|
||||||
"send": "发送",
|
"send": "发送",
|
||||||
"placeholder": "输入您的查询...",
|
"placeholder": "输入查询...",
|
||||||
"error": "错误:无法获取响应"
|
"error": "错误:获取响应失败"
|
||||||
},
|
},
|
||||||
"querySettings": {
|
"querySettings": {
|
||||||
"parametersTitle": "参数设置",
|
"parametersTitle": "参数",
|
||||||
"parametersDescription": "配置查询参数",
|
"parametersDescription": "配置查询参数",
|
||||||
|
|
||||||
"queryMode": "查询模式",
|
"queryMode": "查询模式",
|
||||||
"queryModeTooltip": "选择检索策略:\n• 朴素:不使用高级技术的基本搜索\n• 本地:基于上下文的信息检索\n• 全局:利用全局知识库\n• 混合:结合本地和全局检索\n• 综合:集成知识图谱与向量检索",
|
"queryModeTooltip": "选择检索策略:\n• Naive:基础搜索,无高级技术\n• Local:上下文相关信息检索\n• Global:利用全局知识库\n• Hybrid:结合本地和全局检索\n• Mix:整合知识图谱和向量检索",
|
||||||
"queryModeOptions": {
|
"queryModeOptions": {
|
||||||
"naive": "朴素",
|
"naive": "朴素",
|
||||||
"local": "本地",
|
"local": "本地",
|
||||||
"global": "全局",
|
"global": "全局",
|
||||||
"hybrid": "混合",
|
"hybrid": "混合",
|
||||||
"mix": "综合"
|
"mix": "混合"
|
||||||
},
|
},
|
||||||
|
|
||||||
"responseFormat": "响应格式",
|
"responseFormat": "响应格式",
|
||||||
"responseFormatTooltip": "定义响应格式。例如:\n• 多个段落\n• 单个段落\n• 项目符号",
|
"responseFormatTooltip": "定义响应格式。例如:\n• 多段落\n• 单段落\n• 要点",
|
||||||
"responseFormatOptions": {
|
"responseFormatOptions": {
|
||||||
"multipleParagraphs": "多个段落",
|
"multipleParagraphs": "多段落",
|
||||||
"singleParagraph": "单个段落",
|
"singleParagraph": "单段落",
|
||||||
"bulletPoints": "项目符号"
|
"bulletPoints": "要点"
|
||||||
},
|
},
|
||||||
|
"topK": "Top K结果",
|
||||||
"topK": "Top K 结果数",
|
"topKTooltip": "检索的顶部项目数。在'local'模式下表示实体,在'global'模式下表示关系",
|
||||||
"topKTooltip": "要检索的前 K 个项目数量。在“本地”模式下表示实体,在“全局”模式下表示关系",
|
"topKPlaceholder": "结果数量",
|
||||||
"topKPlaceholder": "结果数",
|
"maxTokensTextUnit": "文本单元最大令牌数",
|
||||||
|
"maxTokensTextUnitTooltip": "每个检索文本块允许的最大令牌数",
|
||||||
"maxTokensTextUnit": "文本单元最大 Token 数",
|
"maxTokensGlobalContext": "全局上下文最大令牌数",
|
||||||
"maxTokensTextUnitTooltip": "每个检索到的文本块允许的最大 Token 数",
|
"maxTokensGlobalContextTooltip": "全局检索中关系描述的最大令牌数",
|
||||||
|
"maxTokensLocalContext": "本地上下文最大令牌数",
|
||||||
"maxTokensGlobalContext": "全局上下文最大 Token 数",
|
"maxTokensLocalContextTooltip": "本地检索中实体描述的最大令牌数",
|
||||||
"maxTokensGlobalContextTooltip": "在全局检索中为关系描述分配的最大 Token 数",
|
|
||||||
|
|
||||||
"maxTokensLocalContext": "本地上下文最大 Token 数",
|
|
||||||
"maxTokensLocalContextTooltip": "在本地检索中为实体描述分配的最大 Token 数",
|
|
||||||
|
|
||||||
"historyTurns": "历史轮次",
|
"historyTurns": "历史轮次",
|
||||||
"historyTurnsTooltip": "在响应上下文中考虑的完整对话轮次(用户-助手对)",
|
"historyTurnsTooltip": "响应上下文中考虑的完整对话轮次(用户-助手对)数量",
|
||||||
"historyTurnsPlaceholder": "历史轮次的数量",
|
"historyTurnsPlaceholder": "历史轮次数",
|
||||||
|
|
||||||
"hlKeywords": "高级关键词",
|
"hlKeywords": "高级关键词",
|
||||||
"hlKeywordsTooltip": "检索时优先考虑的高级关键词。请用逗号分隔",
|
"hlKeywordsTooltip": "检索中优先考虑的高级关键词列表。用逗号分隔",
|
||||||
"hlkeywordsPlaceHolder": "输入关键词",
|
"hlkeywordsPlaceHolder": "输入关键词",
|
||||||
|
|
||||||
"llKeywords": "低级关键词",
|
"llKeywords": "低级关键词",
|
||||||
"llKeywordsTooltip": "用于优化检索焦点的低级关键词。请用逗号分隔",
|
"llKeywordsTooltip": "用于细化检索重点的低级关键词列表。用逗号分隔",
|
||||||
|
"onlyNeedContext": "仅需上下文",
|
||||||
"onlyNeedContext": "仅需要上下文",
|
"onlyNeedContextTooltip": "如果为True,仅返回检索到的上下文而不生成响应",
|
||||||
"onlyNeedContextTooltip": "如果为 True,则仅返回检索到的上下文,而不会生成回复",
|
"onlyNeedPrompt": "仅需提示",
|
||||||
|
"onlyNeedPromptTooltip": "如果为True,仅返回生成的提示而不产生响应",
|
||||||
"onlyNeedPrompt": "仅需要提示",
|
|
||||||
"onlyNeedPromptTooltip": "如果为 True,则仅返回生成的提示,而不会生成回复",
|
|
||||||
|
|
||||||
"streamResponse": "流式响应",
|
"streamResponse": "流式响应",
|
||||||
"streamResponseTooltip": "如果为 True,则启用流式输出以获得实时响应"
|
"streamResponseTooltip": "如果为True,启用实时流式输出响应"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,7 @@ import { Message, QueryRequest } from '@/api/lightrag'
|
|||||||
import { useGraphStore } from '@/stores/graph'
|
import { useGraphStore } from '@/stores/graph'
|
||||||
|
|
||||||
type Theme = 'dark' | 'light' | 'system'
|
type Theme = 'dark' | 'light' | 'system'
|
||||||
|
type Language = 'en' | 'zh'
|
||||||
type Tab = 'documents' | 'knowledge-graph' | 'retrieval' | 'api'
|
type Tab = 'documents' | 'knowledge-graph' | 'retrieval' | 'api'
|
||||||
|
|
||||||
interface SettingsState {
|
interface SettingsState {
|
||||||
@@ -48,6 +49,9 @@ interface SettingsState {
|
|||||||
theme: Theme
|
theme: Theme
|
||||||
setTheme: (theme: Theme) => void
|
setTheme: (theme: Theme) => void
|
||||||
|
|
||||||
|
language: Language
|
||||||
|
setLanguage: (lang: Language) => void
|
||||||
|
|
||||||
enableHealthCheck: boolean
|
enableHealthCheck: boolean
|
||||||
setEnableHealthCheck: (enable: boolean) => void
|
setEnableHealthCheck: (enable: boolean) => void
|
||||||
|
|
||||||
@@ -59,6 +63,7 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|||||||
persist(
|
persist(
|
||||||
(set) => ({
|
(set) => ({
|
||||||
theme: 'system',
|
theme: 'system',
|
||||||
|
language: 'zh',
|
||||||
refreshLayout: () => {
|
refreshLayout: () => {
|
||||||
const graphState = useGraphStore.getState();
|
const graphState = useGraphStore.getState();
|
||||||
const currentGraph = graphState.sigmaGraph;
|
const currentGraph = graphState.sigmaGraph;
|
||||||
@@ -110,6 +115,13 @@ const useSettingsStoreBase = create<SettingsState>()(
|
|||||||
|
|
||||||
setTheme: (theme: Theme) => set({ theme }),
|
setTheme: (theme: Theme) => set({ theme }),
|
||||||
|
|
||||||
|
setLanguage: (language: Language) => {
|
||||||
|
import('i18next').then(({ default: i18n }) => {
|
||||||
|
i18n.changeLanguage(language);
|
||||||
|
});
|
||||||
|
set({ language });
|
||||||
|
},
|
||||||
|
|
||||||
setGraphLayoutMaxIterations: (iterations: number) =>
|
setGraphLayoutMaxIterations: (iterations: number) =>
|
||||||
set({
|
set({
|
||||||
graphLayoutMaxIterations: iterations
|
graphLayoutMaxIterations: iterations
|
||||||
|
Reference in New Issue
Block a user