feat(i18n): add internationalization support across multiple components
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
Box,
|
||||
Typography,
|
||||
@@ -38,6 +39,7 @@ import logger from '@/utils/logger';
|
||||
function KnowledgeBaseDetail() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
|
||||
// 状态管理
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -114,20 +116,20 @@ function KnowledgeBaseDetail() {
|
||||
refreshFiles();
|
||||
fetchKnowledgeDetail();
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || err.message || '删除文件失败');
|
||||
setError(err.response?.data?.message || err.message || t('knowledgeDetails.deleteFileFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
// 上传文件处理
|
||||
const handleUploadFiles = async (uploadFiles: File[]) => {
|
||||
console.log('上传文件:', uploadFiles);
|
||||
console.log(t('knowledgeDetails.uploadFiles'), uploadFiles);
|
||||
const kb_id = knowledgeBase?.id || '';
|
||||
try {
|
||||
await uploadDocuments(kb_id, uploadFiles);
|
||||
refreshFiles();
|
||||
fetchKnowledgeDetail();
|
||||
} catch (err: any) {
|
||||
throw new Error(err.response?.data?.message || err.message || '上传文件失败');
|
||||
throw new Error(err.response?.data?.message || err.message || t('knowledgeDetails.uploadFileFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,7 +140,7 @@ function KnowledgeBaseDetail() {
|
||||
refreshFiles(); // 刷新列表
|
||||
startPolling(); // 开始轮询
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || err.message || '重新解析失败');
|
||||
setError(err.response?.data?.message || err.message || t('knowledgeDetails.reparseFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -148,7 +150,7 @@ function KnowledgeBaseDetail() {
|
||||
await renameDocument(fileId, newName);
|
||||
refreshFiles();
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || err.message || '重命名失败');
|
||||
setError(err.response?.data?.message || err.message || t('knowledgeDetails.renameFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,7 +160,7 @@ function KnowledgeBaseDetail() {
|
||||
await changeDocumentStatus(fileIds, status);
|
||||
refreshFiles();
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || err.message || '更改状态失败');
|
||||
setError(err.response?.data?.message || err.message || t('knowledgeDetails.changeStatusFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,20 +170,20 @@ function KnowledgeBaseDetail() {
|
||||
await cancelRunDocuments(fileIds);
|
||||
refreshFiles();
|
||||
} catch (err: any) {
|
||||
setError(err.response?.data?.message || err.message || '取消运行失败');
|
||||
setError(err.response?.data?.message || err.message || t('knowledgeDetails.cancelRunFailed'));
|
||||
}
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const handleViewDetails = (file: IKnowledgeFile) => {
|
||||
console.log("查看详情:", file);
|
||||
console.log(t('knowledgeDetails.viewDetails'), file);
|
||||
|
||||
navigate(`/chunk/parsed-result?kb_id=${id}&doc_id=${file.id}`);
|
||||
};
|
||||
|
||||
// 查看解析详情
|
||||
const handleViewProcessDetails = (file: IKnowledgeFile) => {
|
||||
console.log("查看解析详情:", file);
|
||||
console.log(t('knowledgeDetails.viewProcessDetails'), file);
|
||||
setSelectedFileDetails(file);
|
||||
setProcessDetailsDialogOpen(true);
|
||||
};
|
||||
@@ -262,7 +264,7 @@ function KnowledgeBaseDetail() {
|
||||
return (
|
||||
<Box sx={{ p: 3 }}>
|
||||
<LinearProgress />
|
||||
<Typography sx={{ mt: 2 }}>加载中...</Typography>
|
||||
<Typography sx={{ mt: 2 }}>{t('common.loading')}</Typography>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -281,11 +283,11 @@ function KnowledgeBaseDetail() {
|
||||
<KnowledgeBreadcrumbs
|
||||
kbItems={[
|
||||
{
|
||||
label: '知识库',
|
||||
label: t('knowledgeDetails.knowledgeBase'),
|
||||
path: '/knowledge'
|
||||
},
|
||||
{
|
||||
label: knowledgeBase?.name || '知识库详情',
|
||||
label: knowledgeBase?.name || t('knowledgeDetails.knowledgeBaseDetail'),
|
||||
path: `/knowledge/${id}`
|
||||
}
|
||||
]}
|
||||
@@ -302,8 +304,8 @@ function KnowledgeBaseDetail() {
|
||||
onChange={(event, newValue) => setCurrentTab(newValue)}
|
||||
sx={{ borderBottom: 1, borderColor: 'divider' }}
|
||||
>
|
||||
<Tab label="Documents" />
|
||||
<Tab label="Graph" />
|
||||
<Tab label={t('knowledgeDetails.documents')} />
|
||||
<Tab label={t('knowledgeDetails.graph')} />
|
||||
</Tabs>
|
||||
|
||||
{/* Document List 标签页内容 */}
|
||||
@@ -365,7 +367,7 @@ function KnowledgeBaseDetail() {
|
||||
onSearchChange={setSearchKeyword}
|
||||
onReparse={(fileIds) => handleReparse(fileIds)}
|
||||
onDelete={(fileIds) => {
|
||||
console.log('删除文件:', fileIds);
|
||||
console.log(t('knowledgeDetails.deleteFiles'), fileIds);
|
||||
setRowSelectionModel({
|
||||
type: 'include',
|
||||
ids: new Set(fileIds)
|
||||
@@ -379,7 +381,7 @@ function KnowledgeBaseDetail() {
|
||||
}}
|
||||
rowSelectionModel={rowSelectionModel}
|
||||
onRowSelectionModelChange={(newModel) => {
|
||||
console.log('新的选择模型:', newModel);
|
||||
console.log(t('knowledgeDetails.newSelectionModel'), newModel);
|
||||
setRowSelectionModel(newModel);
|
||||
}}
|
||||
total={total}
|
||||
@@ -410,7 +412,7 @@ function KnowledgeBaseDetail() {
|
||||
open={uploadDialogOpen}
|
||||
onClose={() => setUploadDialogOpen(false)}
|
||||
onUpload={handleUploadFiles}
|
||||
title="上传文件到知识库"
|
||||
title={t('knowledgeDetails.uploadFilesToKnowledge')}
|
||||
acceptedFileTypes={['.pdf', '.docx', '.txt', '.md', '.png', '.jpg', '.jpeg', '.mp4', '.wav']}
|
||||
maxFileSize={100}
|
||||
maxFiles={10}
|
||||
@@ -418,15 +420,15 @@ function KnowledgeBaseDetail() {
|
||||
|
||||
{/* 删除确认对话框 */}
|
||||
<Dialog open={deleteDialogOpen} onClose={() => setDeleteDialogOpen(false)}>
|
||||
<DialogTitle>确认删除</DialogTitle>
|
||||
<DialogTitle>{t('knowledgeDetails.confirmDelete')}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography>
|
||||
确定要删除选中的 {rowSelectionModel.ids.size} 个文件吗?此操作不可撤销。
|
||||
{t('knowledgeDetails.confirmDeleteMessage', { count: rowSelectionModel.ids.size })}
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setDeleteDialogOpen(false)}>取消</Button>
|
||||
<Button color="error" onClick={handleDeleteFiles}>删除</Button>
|
||||
<Button onClick={() => setDeleteDialogOpen(false)}>{t('common.cancel')}</Button>
|
||||
<Button color="error" onClick={handleDeleteFiles}>{t('common.delete')}</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
@@ -437,7 +439,7 @@ function KnowledgeBaseDetail() {
|
||||
maxWidth="md"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitle>文档处理详情</DialogTitle>
|
||||
<DialogTitle>{t('knowledgeDetails.documentProcessDetails')}</DialogTitle>
|
||||
<DialogContent sx={{ p: 3 }}>
|
||||
{selectedFileDetails && (
|
||||
<Stack spacing={3}>
|
||||
@@ -445,12 +447,12 @@ function KnowledgeBaseDetail() {
|
||||
<Card variant="outlined">
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom color="primary">
|
||||
基本信息
|
||||
{t('knowledgeDetails.basicInfo')}
|
||||
</Typography>
|
||||
<Stack spacing={2}>
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||
文件名
|
||||
{t('knowledgeDetails.fileName')}
|
||||
</Typography>
|
||||
<Typography variant="body1" sx={{ fontWeight: 500 }}>
|
||||
{selectedFileDetails.name}
|
||||
@@ -459,10 +461,10 @@ function KnowledgeBaseDetail() {
|
||||
<Divider />
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||
解析器ID
|
||||
{t('knowledgeDetails.parserId')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{selectedFileDetails.parser_id || '未指定'}
|
||||
{selectedFileDetails.parser_id || t('knowledgeDetails.notSpecified')}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
@@ -473,30 +475,30 @@ function KnowledgeBaseDetail() {
|
||||
<Card variant="outlined">
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom color="primary">
|
||||
处理状态
|
||||
{t('knowledgeDetails.processStatus')}
|
||||
</Typography>
|
||||
<Stack spacing={2}>
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||
开始时间
|
||||
{t('knowledgeDetails.startTime')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{selectedFileDetails.process_begin_at || '未开始'}
|
||||
{selectedFileDetails.process_begin_at || t('knowledgeDetails.notStarted')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider />
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||
处理时长
|
||||
{t('knowledgeDetails.processingTime')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{selectedFileDetails.process_duration ? `${selectedFileDetails.process_duration}秒` : '未完成'}
|
||||
{selectedFileDetails.process_duration ? `${selectedFileDetails.process_duration}${t('knowledgeDetails.seconds')}` : t('knowledgeDetails.notCompleted')}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Divider />
|
||||
<Box>
|
||||
<Typography variant="subtitle2" color="text.secondary" gutterBottom>
|
||||
进度
|
||||
{t('knowledgeDetails.progress')}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<Chip
|
||||
@@ -520,7 +522,7 @@ function KnowledgeBaseDetail() {
|
||||
<Card variant="outlined">
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom color="primary">
|
||||
处理详情
|
||||
{t('knowledgeDetails.processDetails')}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
@@ -556,8 +558,8 @@ function KnowledgeBaseDetail() {
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ p: 3, pt: 0 }}>
|
||||
<Button onClick={() => setProcessDetailsDialogOpen(false)} variant="contained">
|
||||
关闭
|
||||
</Button>
|
||||
{t('common.close')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user