From 3b1ee769ebdbdb518f49fcff2ace7ac06717c4ce Mon Sep 17 00:00:00 2001 From: chanx <1243304602@qq.com> Date: Fri, 5 Sep 2025 09:57:15 +0800 Subject: [PATCH] fix: Optimize internationalization configuration #3221 (#9924) ### What problem does this PR solve? fix: Optimize internationalization configuration - Update multi-language options, adding general translations for functions like Select All and Clear - Add internationalization support for modules like Chat, Search, and Datasets ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --- .../components/cross-language-form-field.tsx | 7 ++++- web/src/components/delimiter-form-field.tsx | 1 + .../indented-tree/indented-tree.tsx | 6 ++-- web/src/components/knowledge-base-item.tsx | 4 ++- .../list-filter-bar/filter-popover.tsx | 5 +-- .../max-token-number-from-field.tsx | 1 + web/src/components/message-input/next.tsx | 3 +- .../raptor-form-fields.tsx | 4 ++- web/src/components/ui/form.tsx | 4 ++- web/src/components/ui/multi-select.tsx | 9 +++--- web/src/locales/en.ts | 29 ++++++++++++++++- web/src/locales/zh.ts | 31 +++++++++++++++++-- web/src/pages/agent/index.tsx | 2 +- web/src/pages/agents/index.tsx | 2 +- web/src/pages/agents/template-sidebar.tsx | 26 ++++++++++++---- .../components/chunk-creating-modal/index.tsx | 4 +-- .../components/chunk-result-bar/index.tsx | 5 ++- .../setting/configuration/common-item.tsx | 2 ++ web/src/pages/dataset/setting/utils.ts | 1 + .../pages/dataset/testing/testing-form.tsx | 2 +- web/src/pages/datasets/dataset-card.tsx | 6 +++- web/src/pages/datasets/index.tsx | 2 +- web/src/pages/files/index.tsx | 6 +++- web/src/pages/home/applications.tsx | 4 +-- web/src/pages/home/datasets.tsx | 2 +- .../chat/app-settings/chat-basic-settings.tsx | 13 ++++++-- .../chat/app-settings/chat-prompt-engine.tsx | 3 +- .../chat/chat-box/multiple-chat-box.tsx | 3 +- web/src/pages/next-chats/chat/index.tsx | 6 ++-- web/src/pages/next-chats/chat/sessions.tsx | 2 +- web/src/pages/next-chats/index.tsx | 2 +- web/src/pages/next-search/index.tsx | 2 +- web/src/pages/next-search/search-setting.tsx | 14 ++++++--- web/src/pages/next-search/search-view.tsx | 2 +- web/src/pages/next-searches/index.tsx | 2 +- web/tailwind.config.js | 9 ++++++ 36 files changed, 175 insertions(+), 51 deletions(-) diff --git a/web/src/components/cross-language-form-field.tsx b/web/src/components/cross-language-form-field.tsx index ec10736b4..9f7dc9a05 100644 --- a/web/src/components/cross-language-form-field.tsx +++ b/web/src/components/cross-language-form-field.tsx @@ -6,6 +6,8 @@ import { } from '@/components/ui/form'; import { MultiSelect } from '@/components/ui/multi-select'; import { cn } from '@/lib/utils'; +import { t } from 'i18next'; +import { toLower } from 'lodash'; import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -20,7 +22,10 @@ const Languages = [ 'Vietnamese', ]; -const options = Languages.map((x) => ({ label: x, value: x })); +const options = Languages.map((x) => ({ + label: t('language.' + toLower(x)), + value: x, +})); type CrossLanguageItemProps = { name?: string; diff --git a/web/src/components/delimiter-form-field.tsx b/web/src/components/delimiter-form-field.tsx index 7374945e3..2ca5d09a3 100644 --- a/web/src/components/delimiter-form-field.tsx +++ b/web/src/components/delimiter-form-field.tsx @@ -52,6 +52,7 @@ export function DelimiterFormField() {
diff --git a/web/src/components/indented-tree/indented-tree.tsx b/web/src/components/indented-tree/indented-tree.tsx index 91ee361b2..cb9583cca 100644 --- a/web/src/components/indented-tree/indented-tree.tsx +++ b/web/src/components/indented-tree/indented-tree.tsx @@ -18,6 +18,7 @@ import { TreeData } from '@antv/g6/lib/types'; import isEmpty from 'lodash/isEmpty'; import React, { useCallback, useEffect, useRef } from 'react'; import { ErrorBoundary, FallbackProps } from 'react-error-boundary'; +import { useIsDarkTheme } from '../theme-provider'; const rootId = 'root'; @@ -322,7 +323,7 @@ const IndentedTree = ({ data, show, style = {} }: IProps) => { node.children.forEach((child, idx) => assignIds(child, node.id, idx)); } }, []); - + const isDark = useIsDarkTheme(); const render = useCallback( async (data: TreeData) => { const graph: Graph = new Graph({ @@ -335,7 +336,8 @@ const IndentedTree = ({ data, show, style = {} }: IProps) => { labelBackground: (datum) => datum.id === rootId, labelBackgroundRadius: 0, labelBackgroundFill: '#576286', - labelFill: (datum) => (datum.id === rootId ? '#fff' : '#666'), + labelFill: isDark ? '#fff' : '#333', + // labelFill: (datum) => (datum.id === rootId ? '#fff' : '#666'), labelText: (d) => d.style?.labelText || d.id, labelTextAlign: (datum) => datum.id === rootId ? 'center' : 'left', diff --git a/web/src/components/knowledge-base-item.tsx b/web/src/components/knowledge-base-item.tsx index b2ec7117e..cb907df56 100644 --- a/web/src/components/knowledge-base-item.tsx +++ b/web/src/components/knowledge-base-item.tsx @@ -134,7 +134,9 @@ export function KnowledgeBaseFormField({ name="kb_ids" render={({ field }) => ( - {t('chat.knowledgeBases')} + + {t('chat.knowledgeBases')} + - Clear + {t('common.clear')}
diff --git a/web/src/components/max-token-number-from-field.tsx b/web/src/components/max-token-number-from-field.tsx index f1762c1a8..b01598d93 100644 --- a/web/src/components/max-token-number-from-field.tsx +++ b/web/src/components/max-token-number-from-field.tsx @@ -14,6 +14,7 @@ export function MaxTokenNumberFormField({ max = 2048, initialValue }: IProps) { { tooltip={t('useRaptorTip')} className="text-sm text-muted-foreground w-1/4 whitespace-break-spaces" > - {t('useRaptor')} +
+ {t('useRaptor')} +
diff --git a/web/src/components/ui/form.tsx b/web/src/components/ui/form.tsx index 8ce3a37cb..a35030542 100644 --- a/web/src/components/ui/form.tsx +++ b/web/src/components/ui/form.tsx @@ -94,8 +94,9 @@ const FormLabel = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef & { tooltip?: React.ReactNode; + required?: boolean; } ->(({ className, tooltip, ...props }, ref) => { +>(({ className, tooltip, required = false, ...props }, ref) => { const { error, formItemId } = useFormField(); return ( @@ -105,6 +106,7 @@ const FormLabel = React.forwardRef< htmlFor={formItemId} {...props} > + {required && *} {props.children} {tooltip && } diff --git a/web/src/components/ui/multi-select.tsx b/web/src/components/ui/multi-select.tsx index 252eb855c..fbdff98f5 100644 --- a/web/src/components/ui/multi-select.tsx +++ b/web/src/components/ui/multi-select.tsx @@ -29,6 +29,7 @@ import { } from '@/components/ui/popover'; import { Separator } from '@/components/ui/separator'; import { cn } from '@/lib/utils'; +import { t } from 'i18next'; import { isEmpty } from 'lodash'; export type MultiSelectOptionType = { @@ -193,7 +194,7 @@ export const MultiSelect = React.forwardRef< onValueChange, variant, defaultValue = [], - placeholder = 'Select options', + placeholder = t('common.selectPlaceholder'), animation = 0, maxCount = 3, modalPopover = false, @@ -379,7 +380,7 @@ export const MultiSelect = React.forwardRef< > @@ -401,7 +402,7 @@ export const MultiSelect = React.forwardRef< >
- (Select All) + ({t('common.selectAll')}) )} {!options.some((x) => 'options' in x) && @@ -457,7 +458,7 @@ export const MultiSelect = React.forwardRef< onSelect={() => setIsPopoverOpen(false)} className="flex-1 justify-center cursor-pointer max-w-full" > - Close + {t('common.close')} diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index 18ce603c0..2edf2404c 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -3,6 +3,7 @@ export default { common: { noResults: 'No results.', selectPlaceholder: 'select value', + selectAll: 'Select All', delete: 'Delete', deleteModalTitle: 'Are you sure to delete this item?', ok: 'Yes', @@ -37,6 +38,7 @@ export default { pleaseSelect: 'Please select', pleaseInput: 'Please input', submit: 'Submit', + clear: 'Clear', embedIntoSite: 'Embed into webpage', previousPage: 'Previous', nextPage: 'Next', @@ -145,7 +147,8 @@ export default { vectorSimilarityWeightTip: 'This sets the weight of keyword similarity in the combined similarity score, either used with vector cosine similarity or with reranking score. The total of the two weights must equal 1.0.', keywordSimilarityWeight: 'Keyword similarity weight', - keywordSimilarityWeightTip: '', + keywordSimilarityWeightTip: + 'This sets the weight of keyword similarity in the combined similarity score, either used with vector cosine similarity or with reranking score. The total of the two weights must equal 1.0.', testText: 'Test text', testTextPlaceholder: 'Input your question here!', testingLabel: 'Testing', @@ -441,6 +444,12 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s delete: 'Delete', }, chat: { + messagePlaceholder: 'Type your message here...', + exit: 'Exit', + multipleModels: 'Multiple Models', + applyModelConfigs: 'Apply model configs', + conversations: 'Conversations', + chatApps: 'Chat Apps', newConversation: 'New conversation', createAssistant: 'Create an Assistant', assistantSetting: 'Assistant settings', @@ -839,6 +848,7 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s hint: 'hint', }, fileManager: { + files: 'Files', name: 'Name', uploadDate: 'Upload Date', knowledgeBase: 'Dataset', @@ -864,6 +874,12 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s pleaseUploadAtLeastOneFile: 'Please upload at least one file', }, flow: { + recommended: 'Recommended', + customerSupport: 'Customer Support', + marketing: 'Marketing', + consumerApp: 'Consumer App', + other: 'Other', + agents: 'Agents', days: 'Days', beginInput: 'Begin Input', ref: 'Variable', @@ -1527,6 +1543,7 @@ This delimiter is used to split the input text into several text pieces echo of editMCP: 'Edit MCP', }, search: { + searchApps: 'Search Apps', createSearch: 'Create Search', searchGreeting: 'How can I help you today ?', profile: 'Hide Profile', @@ -1551,5 +1568,15 @@ This delimiter is used to split the input text into several text pieces echo of okText: 'Save', cancelText: 'Cancel', }, + language: { + english: 'English', + chinese: 'Chinese', + spanish: 'Spanish', + french: 'French', + german: 'German', + japanese: 'Japanese', + korean: 'Korean', + vietnamese: 'Vietnamese', + }, }, }; diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index fec9c3428..973a9ac9a 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -3,6 +3,7 @@ export default { common: { noResults: '无结果。', selectPlaceholder: '请选择', + selectAll: '全选', delete: '删除', deleteModalTitle: '确定删除吗?', ok: '是', @@ -36,6 +37,7 @@ export default { pleaseSelect: '请选择', pleaseInput: '请输入', submit: '提交', + clear: '清空', embedIntoSite: '嵌入网站', previousPage: '上一页', nextPage: '下一页', @@ -105,7 +107,7 @@ export default { testing: '检索测试', configuration: '配置', knowledgeGraph: '知识图谱', - files: '文件', + files: '个文件', name: '名称', namePlaceholder: '请输入名称', doc: '文档', @@ -136,7 +138,8 @@ export default { vectorSimilarityWeightTip: '我们使用混合相似性评分来评估两行文本之间的距离。它是加权关键字相似性和矢量余弦相似性或rerank得分(0〜1)。两个权重的总和为1.0。', keywordSimilarityWeight: '关键词相似度权重', - keywordSimilarityWeightTip: '', + keywordSimilarityWeightTip: + '我们使用混合相似性评分来评估两行文本之间的距离。它是加权关键字相似性和矢量余弦相似性或rerank得分(0〜1)。两个权重的总和为1.0。', testText: '测试文本', testTextPlaceholder: '请输入您的问题!', testingLabel: '测试', @@ -440,6 +443,12 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 delete: '删除', }, chat: { + messagePlaceholder: '请输入消息...', + exit: '退出', + multipleModels: '多模型', + applyModelConfigs: '应用模型配置', + conversations: '会话', + chatApps: '聊天', createChat: '创建聊天', newConversation: '新会话', createAssistant: '新建助理', @@ -798,6 +807,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 hint: '提示', }, fileManager: { + files: '文件', name: '名称', uploadDate: '上传日期', knowledgeBase: '知识库', @@ -822,6 +832,12 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 pleaseUploadAtLeastOneFile: '请上传至少一个文件', }, flow: { + recommended: '推荐', + customerSupport: '客户支持', + marketing: '营销', + consumerApp: '消费者应用', + other: '其他', + agents: '智能体', beginInput: '开始输入', seconds: '秒', ref: '引用变量', @@ -1441,6 +1457,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 cancelText: '取消', }, search: { + searchApps: '搜索', createSearch: '创建查询', searchGreeting: '今天我能为你做些什么?', profile: '隐藏个人资料', @@ -1465,5 +1482,15 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 okText: '保存', cancelText: '返回', }, + language: { + english: '英语', + chinese: '中文', + spanish: '西班牙语', + french: '法语', + german: '德语', + japanese: '日语', + korean: '韩语', + vietnamese: '越南语', + }, }, }; diff --git a/web/src/pages/agent/index.tsx b/web/src/pages/agent/index.tsx index c2ef597b7..b356a9319 100644 --- a/web/src/pages/agent/index.tsx +++ b/web/src/pages/agent/index.tsx @@ -114,7 +114,7 @@ export default function Agent() { - Agent + {t('header.flow')} diff --git a/web/src/pages/agents/index.tsx b/web/src/pages/agents/index.tsx index 3779290ee..d4d5c913a 100644 --- a/web/src/pages/agents/index.tsx +++ b/web/src/pages/agents/index.tsx @@ -36,7 +36,7 @@ export default function Agents() {
& kFProps> = ({ render={({ field }) => ( -
+
{t('chunk.question')} - + ? diff --git a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx index 6441fc1b1..2d392ead6 100644 --- a/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx +++ b/web/src/pages/chunk/parsed-result/add-knowledge/components/knowledge-chunk/components/chunk-result-bar/index.tsx @@ -95,7 +95,10 @@ export default ({
-
diff --git a/web/src/pages/dataset/setting/configuration/common-item.tsx b/web/src/pages/dataset/setting/configuration/common-item.tsx index 66287d754..5706b671f 100644 --- a/web/src/pages/dataset/setting/configuration/common-item.tsx +++ b/web/src/pages/dataset/setting/configuration/common-item.tsx @@ -28,6 +28,7 @@ export function ChunkMethodItem() {
@@ -68,6 +69,7 @@ export function EmbeddingModelItem() {
diff --git a/web/src/pages/dataset/setting/utils.ts b/web/src/pages/dataset/setting/utils.ts index ceb9cc97e..4c5666467 100644 --- a/web/src/pages/dataset/setting/utils.ts +++ b/web/src/pages/dataset/setting/utils.ts @@ -16,4 +16,5 @@ export const ImageMap = { table: getImageName('table', 2), one: getImageName('one', 2), knowledge_graph: getImageName('knowledge-graph', 2), + tag: getImageName('tag', 2), }; diff --git a/web/src/pages/dataset/testing/testing-form.tsx b/web/src/pages/dataset/testing/testing-form.tsx index 983fe6fea..ba614ed67 100644 --- a/web/src/pages/dataset/testing/testing-form.tsx +++ b/web/src/pages/dataset/testing/testing-form.tsx @@ -83,7 +83,7 @@ export default function TestingForm({ diff --git a/web/src/pages/datasets/dataset-card.tsx b/web/src/pages/datasets/dataset-card.tsx index 897ce818d..ff92c85e8 100644 --- a/web/src/pages/datasets/dataset-card.tsx +++ b/web/src/pages/datasets/dataset-card.tsx @@ -4,6 +4,7 @@ import { SharedBadge } from '@/components/shared-badge'; import { Card, CardContent } from '@/components/ui/card'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { IKnowledge } from '@/interfaces/database/knowledge'; +import { t } from 'i18next'; import { ChevronRight } from 'lucide-react'; import { DatasetDropdown } from './dataset-dropdown'; import { useRenameDataset } from './use-rename-dataset'; @@ -20,7 +21,10 @@ export function DatasetCard({ return ( - {breadcrumbItems.length > 0 ? : 'File'} + {breadcrumbItems.length > 0 ? ( + + ) : ( + t('fileManager.files') + )}
); diff --git a/web/src/pages/home/applications.tsx b/web/src/pages/home/applications.tsx index 9147b8a5f..3c2e3ce59 100644 --- a/web/src/pages/home/applications.tsx +++ b/web/src/pages/home/applications.tsx @@ -26,8 +26,8 @@ export function Applications() { const options = useMemo( () => [ - { value: Routes.Chats, label: t('header.chat') }, - { value: Routes.Searches, label: t('header.search') }, + { value: Routes.Chats, label: t('chat.chatApps') }, + { value: Routes.Searches, label: t('search.searchApps') }, { value: Routes.Agents, label: t('header.flow') }, ], [t], diff --git a/web/src/pages/home/datasets.tsx b/web/src/pages/home/datasets.tsx index af4ee1313..f8e27e66c 100644 --- a/web/src/pages/home/datasets.tsx +++ b/web/src/pages/home/datasets.tsx @@ -22,7 +22,7 @@ export function Datasets() {

- {t('header.knowledgeBase')} + {t('header.dataset')}

{loading ? ( diff --git a/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx index 01d2782e6..d945f7841 100644 --- a/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx +++ b/web/src/pages/next-chats/chat/app-settings/chat-basic-settings.tsx @@ -43,7 +43,7 @@ export default function ChatBasicSetting() { name="name" render={({ field }) => ( - {t('assistantName')} + {t('assistantName')} @@ -69,7 +69,9 @@ export default function ChatBasicSetting() { name={'prompt_config.empty_response'} render={({ field }) => ( - {t('emptyResponse')} + + {t('emptyResponse')} + @@ -82,7 +84,9 @@ export default function ChatBasicSetting() { name={'prompt_config.prologue'} render={({ field }) => ( - {t('setAnOpener')} + + {t('setAnOpener')} + @@ -93,14 +97,17 @@ export default function ChatBasicSetting() { diff --git a/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx b/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx index 9a7ed285c..836073335 100644 --- a/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx +++ b/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx @@ -37,11 +37,12 @@ export function ChatPromptEngine() { )} /> - + -

Apply model configs

+

{t('chat.applyModelConfigs')}

{!isLatestChat || chatBoxIds.length === 3 ? ( diff --git a/web/src/pages/next-chats/chat/index.tsx b/web/src/pages/next-chats/chat/index.tsx index 34be965ae..f384a7626 100644 --- a/web/src/pages/next-chats/chat/index.tsx +++ b/web/src/pages/next-chats/chat/index.tsx @@ -63,10 +63,10 @@ export default function Chat() {
- Multiple Models ({chatBoxIds.length}/3) + {t('chat.multipleModels')} ({chatBoxIds.length}/3)
- Multiple Models + {t('chat.multipleModels')} diff --git a/web/src/pages/next-chats/chat/sessions.tsx b/web/src/pages/next-chats/chat/sessions.tsx index 7fde0ad2a..98b707374 100644 --- a/web/src/pages/next-chats/chat/sessions.tsx +++ b/web/src/pages/next-chats/chat/sessions.tsx @@ -71,7 +71,7 @@ export function Sessions({
- Conversations + {t('chat.conversations')} {conversationList.length} diff --git a/web/src/pages/next-chats/index.tsx b/web/src/pages/next-chats/index.tsx index 446a28677..5def23e21 100644 --- a/web/src/pages/next-chats/index.tsx +++ b/web/src/pages/next-chats/index.tsx @@ -38,7 +38,7 @@ export default function ChatList() {
- Search + {t('header.search')} diff --git a/web/src/pages/next-search/search-setting.tsx b/web/src/pages/next-search/search-setting.tsx index 183130683..8a9e136cb 100644 --- a/web/src/pages/next-search/search-setting.tsx +++ b/web/src/pages/next-search/search-setting.tsx @@ -397,7 +397,11 @@ const SearchSetting: React.FC = ({ name="search_config.similarity_threshold" render={({ field }) => ( - Similarity Threshold + + {t('knowledgeDetails.similarityThreshold')} +
= ({ name="search_config.vector_similarity_weight" render={({ field }) => ( - - *Vector - Similarity Weight + + * + {t('knowledgeDetails.vectorSimilarityWeight')}

- {t('relatedSearch')} + {t('search.relatedSearch')}

{relatedQuestions?.map((x, idx) => ( diff --git a/web/src/pages/next-searches/index.tsx b/web/src/pages/next-searches/index.tsx index 935fcee7c..713ed7e64 100644 --- a/web/src/pages/next-searches/index.tsx +++ b/web/src/pages/next-searches/index.tsx @@ -49,7 +49,7 @@ export default function SearchList() {
handleSearchChange(e.target.value)} > diff --git a/web/tailwind.config.js b/web/tailwind.config.js index 27de063ae..c04ca939d 100644 --- a/web/tailwind.config.js +++ b/web/tailwind.config.js @@ -17,6 +17,15 @@ module.exports = { '2xl': '1400px', }, }, + screens: { + sm: '640px', + md: '768px', + lg: '1024px', + xl: '1280px', + '2xl': '1400px', + '3xl': '1780px', + '4xl': '1980px', + }, extend: { colors: { border: 'var(--colors-outline-neutral-strong)',