(feat:upload) i18n

This commit is contained in:
ManishMadan2882
2025-10-03 20:32:43 +05:30
parent 6bb4195393
commit c184b63df8
10 changed files with 484 additions and 57 deletions

View File

@@ -1,5 +1,6 @@
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import { useDarkTheme } from '../hooks'; import { useDarkTheme } from '../hooks';
import { selectToken } from '../preferences/preferenceSlice'; import { selectToken } from '../preferences/preferenceSlice';
@@ -24,6 +25,7 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
onDisconnect, onDisconnect,
errorMessage, errorMessage,
}) => { }) => {
const { t } = useTranslation();
const token = useSelector(selectToken); const token = useSelector(selectToken);
const [isDarkTheme] = useDarkTheme(); const [isDarkTheme] = useDarkTheme();
const completedRef = useRef(false); const completedRef = useRef(false);
@@ -47,12 +49,16 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
cleanup(); cleanup();
onSuccess({ onSuccess({
session_token: event.data.session_token, session_token: event.data.session_token,
user_email: event.data.user_email || 'Connected User', user_email:
event.data.user_email ||
t('modals.uploadDoc.connectors.auth.connectedUser'),
}); });
} else if (errorProvider) { } else if (errorProvider) {
completedRef.current = true; completedRef.current = true;
cleanup(); cleanup();
onError(event.data.error || 'Authentication failed'); onError(
event.data.error || t('modals.uploadDoc.connectors.auth.authFailed'),
);
} }
}; };
@@ -71,13 +77,15 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
if (!authResponse.ok) { if (!authResponse.ok) {
throw new Error( throw new Error(
`Failed to get authorization URL: ${authResponse.status}`, `${t('modals.uploadDoc.connectors.auth.authUrlFailed')}: ${authResponse.status}`,
); );
} }
const authData = await authResponse.json(); const authData = await authResponse.json();
if (!authData.success || !authData.authorization_url) { if (!authData.success || !authData.authorization_url) {
throw new Error(authData.error || 'Failed to get authorization URL'); throw new Error(
authData.error || t('modals.uploadDoc.connectors.auth.authUrlFailed'),
);
} }
const authWindow = window.open( const authWindow = window.open(
@@ -86,9 +94,7 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
'width=500,height=600,scrollbars=yes,resizable=yes', 'width=500,height=600,scrollbars=yes,resizable=yes',
); );
if (!authWindow) { if (!authWindow) {
throw new Error( throw new Error(t('modals.uploadDoc.connectors.auth.popupBlocked'));
'Failed to open authentication window. Please allow popups.',
);
} }
window.addEventListener('message', handleAuthMessage as any); window.addEventListener('message', handleAuthMessage as any);
@@ -98,13 +104,17 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
clearInterval(checkClosed); clearInterval(checkClosed);
window.removeEventListener('message', handleAuthMessage as any); window.removeEventListener('message', handleAuthMessage as any);
if (!completedRef.current) { if (!completedRef.current) {
onError('Authentication was cancelled'); onError(t('modals.uploadDoc.connectors.auth.authCancelled'));
} }
} }
}, 1000); }, 1000);
intervalRef.current = checkClosed; intervalRef.current = checkClosed;
} catch (error) { } catch (error) {
onError(error instanceof Error ? error.message : 'Authentication failed'); onError(
error instanceof Error
? error.message
: t('modals.uploadDoc.connectors.auth.authFailed'),
);
} }
}; };
@@ -147,14 +157,18 @@ const ConnectorAuth: React.FC<ConnectorAuthProps> = ({
d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"
/> />
</svg> </svg>
<span>Connected as {userEmail}</span> <span>
{t('modals.uploadDoc.connectors.auth.connectedAs', {
email: userEmail,
})}
</span>
</div> </div>
{onDisconnect && ( {onDisconnect && (
<button <button
onClick={onDisconnect} onClick={onDisconnect}
className="text-xs font-medium text-[#212121] underline hover:text-gray-700" className="text-xs font-medium text-[#212121] underline hover:text-gray-700"
> >
Disconnect {t('modals.uploadDoc.connectors.auth.disconnect')}
</button> </button>
)} )}
</div> </div>

View File

@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import useDrivePicker from 'react-google-drive-picker'; import useDrivePicker from 'react-google-drive-picker';
import ConnectorAuth from './ConnectorAuth'; import ConnectorAuth from './ConnectorAuth';
@@ -26,6 +27,7 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
token, token,
onSelectionChange, onSelectionChange,
}) => { }) => {
const { t } = useTranslation();
const [selectedFiles, setSelectedFiles] = useState<PickerFile[]>([]); const [selectedFiles, setSelectedFiles] = useState<PickerFile[]>([]);
const [selectedFolders, setSelectedFolders] = useState<PickerFile[]>([]); const [selectedFolders, setSelectedFolders] = useState<PickerFile[]>([]);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
@@ -66,14 +68,19 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
if (!validateResponse.ok) { if (!validateResponse.ok) {
setIsConnected(false); setIsConnected(false);
setAuthError('Session expired. Please reconnect to Google Drive.'); setAuthError(
t('modals.uploadDoc.connectors.googleDrive.sessionExpired'),
);
setIsValidating(false); setIsValidating(false);
return false; return false;
} }
const validateData = await validateResponse.json(); const validateData = await validateResponse.json();
if (validateData.success) { if (validateData.success) {
setUserEmail(validateData.user_email || 'Connected User'); setUserEmail(
validateData.user_email ||
t('modals.uploadDoc.connectors.auth.connectedUser'),
);
setIsConnected(true); setIsConnected(true);
setAuthError(''); setAuthError('');
setAccessToken(validateData.access_token || null); setAccessToken(validateData.access_token || null);
@@ -83,14 +90,14 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
setIsConnected(false); setIsConnected(false);
setAuthError( setAuthError(
validateData.error || validateData.error ||
'Session expired. Please reconnect your account.', t('modals.uploadDoc.connectors.googleDrive.sessionExpiredGeneric'),
); );
setIsValidating(false); setIsValidating(false);
return false; return false;
} }
} catch (error) { } catch (error) {
console.error('Error validating session:', error); console.error('Error validating session:', error);
setAuthError('Failed to validate session. Please reconnect.'); setAuthError(t('modals.uploadDoc.connectors.googleDrive.validateFailed'));
setIsConnected(false); setIsConnected(false);
setIsValidating(false); setIsValidating(false);
return false; return false;
@@ -103,15 +110,13 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const sessionToken = getSessionToken('google_drive'); const sessionToken = getSessionToken('google_drive');
if (!sessionToken) { if (!sessionToken) {
setAuthError('No valid session found. Please reconnect to Google Drive.'); setAuthError(t('modals.uploadDoc.connectors.googleDrive.noSession'));
setIsLoading(false); setIsLoading(false);
return; return;
} }
if (!accessToken) { if (!accessToken) {
setAuthError( setAuthError(t('modals.uploadDoc.connectors.googleDrive.noAccessToken'));
'No access token available. Please reconnect to Google Drive.',
);
setIsLoading(false); setIsLoading(false);
return; return;
} }
@@ -193,7 +198,7 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
}); });
} catch (error) { } catch (error) {
console.error('Error opening picker:', error); console.error('Error opening picker:', error);
setAuthError('Failed to open file picker. Please try again.'); setAuthError(t('modals.uploadDoc.connectors.googleDrive.pickerFailed'));
setIsLoading(false); setIsLoading(false);
} }
}; };
@@ -264,9 +269,12 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
<> <>
<ConnectorAuth <ConnectorAuth
provider="google_drive" provider="google_drive"
label="Connect to Google Drive" label={t('modals.uploadDoc.connectors.googleDrive.connect')}
onSuccess={(data) => { onSuccess={(data) => {
setUserEmail(data.user_email || 'Connected User'); setUserEmail(
data.user_email ||
t('modals.uploadDoc.connectors.auth.connectedUser'),
);
setIsConnected(true); setIsConnected(true);
setAuthError(''); setAuthError('');
@@ -289,26 +297,34 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
<div className="rounded-lg border border-[#EEE6FF78] dark:border-[#6A6A6A]"> <div className="rounded-lg border border-[#EEE6FF78] dark:border-[#6A6A6A]">
<div className="p-4"> <div className="p-4">
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
<h3 className="text-sm font-medium">Selected Files</h3> <h3 className="text-sm font-medium">
{t('modals.uploadDoc.connectors.googleDrive.selectedFiles')}
</h3>
<button <button
onClick={() => handleOpenPicker()} onClick={() => handleOpenPicker()}
className="rounded-md bg-[#A076F6] px-3 py-1 text-sm text-white hover:bg-[#8A5FD4]" className="rounded-md bg-[#A076F6] px-3 py-1 text-sm text-white hover:bg-[#8A5FD4]"
disabled={isLoading} disabled={isLoading}
> >
{isLoading ? 'Loading...' : 'Select Files'} {isLoading
? t('modals.uploadDoc.connectors.googleDrive.loading')
: t(
'modals.uploadDoc.connectors.googleDrive.selectFiles',
)}
</button> </button>
</div> </div>
{selectedFiles.length === 0 && selectedFolders.length === 0 ? ( {selectedFiles.length === 0 && selectedFolders.length === 0 ? (
<p className="text-sm text-gray-600 dark:text-gray-400"> <p className="text-sm text-gray-600 dark:text-gray-400">
No files or folders selected {t(
'modals.uploadDoc.connectors.googleDrive.noFilesSelected',
)}
</p> </p>
) : ( ) : (
<div className="max-h-60 overflow-y-auto"> <div className="max-h-60 overflow-y-auto">
{selectedFolders.length > 0 && ( {selectedFolders.length > 0 && (
<div className="mb-2"> <div className="mb-2">
<h4 className="mb-1 text-xs font-medium text-gray-500"> <h4 className="mb-1 text-xs font-medium text-gray-500">
Folders {t('modals.uploadDoc.connectors.googleDrive.folders')}
</h4> </h4>
{selectedFolders.map((folder) => ( {selectedFolders.map((folder) => (
<div <div
@@ -317,7 +333,9 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
> >
<img <img
src={folder.iconUrl} src={folder.iconUrl}
alt="Folder" alt={t(
'modals.uploadDoc.connectors.googleDrive.folderAlt',
)}
className="mr-2 h-5 w-5" className="mr-2 h-5 w-5"
/> />
<span className="flex-1 truncate text-sm"> <span className="flex-1 truncate text-sm">
@@ -337,7 +355,9 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
}} }}
className="ml-2 text-sm text-red-500 hover:text-red-700" className="ml-2 text-sm text-red-500 hover:text-red-700"
> >
Remove {t(
'modals.uploadDoc.connectors.googleDrive.remove',
)}
</button> </button>
</div> </div>
))} ))}
@@ -347,7 +367,7 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
{selectedFiles.length > 0 && ( {selectedFiles.length > 0 && (
<div> <div>
<h4 className="mb-1 text-xs font-medium text-gray-500"> <h4 className="mb-1 text-xs font-medium text-gray-500">
Files {t('modals.uploadDoc.connectors.googleDrive.files')}
</h4> </h4>
{selectedFiles.map((file) => ( {selectedFiles.map((file) => (
<div <div
@@ -356,7 +376,9 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
> >
<img <img
src={file.iconUrl} src={file.iconUrl}
alt="File" alt={t(
'modals.uploadDoc.connectors.googleDrive.fileAlt',
)}
className="mr-2 h-5 w-5" className="mr-2 h-5 w-5"
/> />
<span className="flex-1 truncate text-sm"> <span className="flex-1 truncate text-sm">
@@ -375,7 +397,9 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
}} }}
className="ml-2 text-sm text-red-500 hover:text-red-700" className="ml-2 text-sm text-red-500 hover:text-red-700"
> >
Remove {t(
'modals.uploadDoc.connectors.googleDrive.remove',
)}
</button> </button>
</div> </div>
))} ))}

View File

@@ -43,7 +43,7 @@ export default function UploadToast() {
case 'failed': case 'failed':
return t('attachments.uploadFailed'); return t('attachments.uploadFailed');
default: default:
return 'Preparing upload'; return t('modals.uploadDoc.progress.preparing');
} }
}; };
@@ -91,8 +91,8 @@ export default function UploadToast() {
onClick={() => toggleTaskCollapse(task.id)} onClick={() => toggleTaskCollapse(task.id)}
aria-label={ aria-label={
isCollapsed isCollapsed
? 'Expand upload details' ? t('modals.uploadDoc.progress.expandDetails')
: 'Collapse upload details' : t('modals.uploadDoc.progress.collapseDetails')
} }
className="flex h-8 items-center justify-center p-0 text-black opacity-70 transition-opacity hover:opacity-100 dark:text-white" className="flex h-8 items-center justify-center p-0 text-black opacity-70 transition-opacity hover:opacity-100 dark:text-white"
> >
@@ -108,7 +108,7 @@ export default function UploadToast() {
type="button" type="button"
onClick={() => dispatch(dismissUploadTask(task.id))} onClick={() => dispatch(dismissUploadTask(task.id))}
className="flex h-8 items-center justify-center p-0 text-black opacity-70 transition-opacity hover:opacity-100 dark:text-white" className="flex h-8 items-center justify-center p-0 text-black opacity-70 transition-opacity hover:opacity-100 dark:text-white"
aria-label="Dismiss upload toast" aria-label={t('modals.uploadDoc.progress.dismiss')}
> >
<svg <svg
width="16" width="16"
@@ -165,7 +165,12 @@ export default function UploadToast() {
aria-valuemin={0} aria-valuemin={0}
aria-valuemax={100} aria-valuemax={100}
aria-valuenow={formattedProgress} aria-valuenow={formattedProgress}
aria-label={`Upload progress ${formattedProgress}%`} aria-label={t(
'modals.uploadDoc.progress.uploadProgress',
{
progress: formattedProgress,
},
)}
> >
<circle <circle
className="text-gray-300 dark:text-gray-700" className="text-gray-300 dark:text-gray-700"
@@ -231,7 +236,7 @@ export default function UploadToast() {
onClick={() => dispatch(clearCompletedTasks())} onClick={() => dispatch(clearCompletedTasks())}
className="mt-1 mr-1 text-right text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200" className="mt-1 mr-1 text-right text-xs text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
> >
Clear {t('modals.uploadDoc.progress.clear')}
</button> </button>
)} )}
</div> </div>

View File

@@ -229,6 +229,9 @@
"uploadDoc": { "uploadDoc": {
"label": "Upload new document", "label": "Upload new document",
"select": "Choose how to upload your document to DocsGPT", "select": "Choose how to upload your document to DocsGPT",
"selectSource": "Select the way to add your source",
"selectedFiles": "Selected Files",
"noFilesSelected": "No files selected",
"file": "Upload from device", "file": "Upload from device",
"back": "Back", "back": "Back",
"wait": "Please wait ...", "wait": "Please wait ...",
@@ -260,10 +263,71 @@
"training": "Training is in progress", "training": "Training is in progress",
"completed": "Training completed", "completed": "Training completed",
"wait": "This may take several minutes", "wait": "This may take several minutes",
"tokenLimit": "Over the token limit, please consider uploading smaller document" "preparing": "Preparing upload",
"tokenLimit": "Over the token limit, please consider uploading smaller document",
"expandDetails": "Expand upload details",
"collapseDetails": "Collapse upload details",
"dismiss": "Dismiss upload toast",
"uploadProgress": "Upload progress {{progress}}%",
"clear": "Clear"
}, },
"showAdvanced": "Show advanced options", "showAdvanced": "Show advanced options",
"hideAdvanced": "Hide advanced options" "hideAdvanced": "Hide advanced options",
"ingestors": {
"local_file": {
"label": "Upload File",
"heading": "Upload new document"
},
"crawler": {
"label": "Crawler",
"heading": "Add content with Web Crawler"
},
"url": {
"label": "Link",
"heading": "Add content from URL"
},
"github": {
"label": "GitHub",
"heading": "Add content from GitHub"
},
"reddit": {
"label": "Reddit",
"heading": "Add content from Reddit"
},
"google_drive": {
"label": "Google Drive",
"heading": "Upload from Google Drive"
}
},
"connectors": {
"auth": {
"connectedUser": "Connected User",
"authFailed": "Authentication failed",
"authUrlFailed": "Failed to get authorization URL",
"popupBlocked": "Failed to open authentication window. Please allow popups.",
"authCancelled": "Authentication was cancelled",
"connectedAs": "Connected as {{email}}",
"disconnect": "Disconnect"
},
"googleDrive": {
"connect": "Connect to Google Drive",
"sessionExpired": "Session expired. Please reconnect to Google Drive.",
"sessionExpiredGeneric": "Session expired. Please reconnect your account.",
"validateFailed": "Failed to validate session. Please reconnect.",
"noSession": "No valid session found. Please reconnect to Google Drive.",
"noAccessToken": "No access token available. Please reconnect to Google Drive.",
"pickerFailed": "Failed to open file picker. Please try again.",
"selectedFiles": "Selected Files",
"selectFiles": "Select Files",
"loading": "Loading...",
"noFilesSelected": "No files or folders selected",
"folders": "Folders",
"files": "Files",
"remove": "Remove",
"folderAlt": "Folder",
"fileAlt": "File"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "Create New API Key", "label": "Create New API Key",

View File

@@ -192,6 +192,9 @@
"uploadDoc": { "uploadDoc": {
"label": "Subir nuevo documento", "label": "Subir nuevo documento",
"select": "Elige cómo cargar tu documento en DocsGPT", "select": "Elige cómo cargar tu documento en DocsGPT",
"selectSource": "Selecciona la forma de agregar tu fuente",
"selectedFiles": "Archivos Seleccionados",
"noFilesSelected": "No hay archivos seleccionados",
"file": "Subir desde el dispositivo", "file": "Subir desde el dispositivo",
"back": "Atrás", "back": "Atrás",
"wait": "Por favor espera ...", "wait": "Por favor espera ...",
@@ -223,10 +226,71 @@
"training": "Entrenamiento en progreso", "training": "Entrenamiento en progreso",
"completed": "Entrenamiento completado", "completed": "Entrenamiento completado",
"wait": "Esto puede tardar varios minutos", "wait": "Esto puede tardar varios minutos",
"tokenLimit": "Excede el límite de tokens, considere cargar un documento más pequeño" "preparing": "Preparando subida",
"tokenLimit": "Excede el límite de tokens, considere cargar un documento más pequeño",
"expandDetails": "Expandir detalles de subida",
"collapseDetails": "Contraer detalles de subida",
"dismiss": "Descartar notificación de subida",
"uploadProgress": "Progreso de subida {{progress}}%",
"clear": "Limpiar"
}, },
"showAdvanced": "Mostrar opciones avanzadas", "showAdvanced": "Mostrar opciones avanzadas",
"hideAdvanced": "Ocultar opciones avanzadas" "hideAdvanced": "Ocultar opciones avanzadas",
"ingestors": {
"local_file": {
"label": "Subir archivo",
"heading": "Subir nuevo documento"
},
"crawler": {
"label": "Rastreador",
"heading": "Agregar contenido con rastreador web"
},
"url": {
"label": "Enlace",
"heading": "Agregar contenido desde URL"
},
"github": {
"label": "GitHub",
"heading": "Agregar contenido desde GitHub"
},
"reddit": {
"label": "Reddit",
"heading": "Agregar contenido desde Reddit"
},
"google_drive": {
"label": "Google Drive",
"heading": "Subir desde Google Drive"
}
},
"connectors": {
"auth": {
"connectedUser": "Usuario Conectado",
"authFailed": "Autenticación fallida",
"authUrlFailed": "Error al obtener la URL de autorización",
"popupBlocked": "Error al abrir la ventana de autenticación. Por favor, permita ventanas emergentes.",
"authCancelled": "Autenticación cancelada",
"connectedAs": "Conectado como {{email}}",
"disconnect": "Desconectar"
},
"googleDrive": {
"connect": "Conectar a Google Drive",
"sessionExpired": "Sesión expirada. Por favor, reconecte a Google Drive.",
"sessionExpiredGeneric": "Sesión expirada. Por favor, reconecte su cuenta.",
"validateFailed": "Error al validar la sesión. Por favor, reconecte.",
"noSession": "No se encontró una sesión válida. Por favor, reconecte a Google Drive.",
"noAccessToken": "No hay token de acceso disponible. Por favor, reconecte a Google Drive.",
"pickerFailed": "Error al abrir el selector de archivos. Por favor, inténtelo de nuevo.",
"selectedFiles": "Archivos Seleccionados",
"selectFiles": "Seleccionar Archivos",
"loading": "Cargando...",
"noFilesSelected": "No hay archivos o carpetas seleccionados",
"folders": "Carpetas",
"files": "Archivos",
"remove": "Eliminar",
"folderAlt": "Carpeta",
"fileAlt": "Archivo"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "Crear Nueva Clave de API", "label": "Crear Nueva Clave de API",

View File

@@ -192,6 +192,9 @@
"uploadDoc": { "uploadDoc": {
"label": "新しい文書をアップロードする", "label": "新しい文書をアップロードする",
"select": "ドキュメントを DocsGPT にアップロードする方法を選択します", "select": "ドキュメントを DocsGPT にアップロードする方法を選択します",
"selectSource": "ソースを追加する方法を選択してください",
"selectedFiles": "選択されたファイル",
"noFilesSelected": "ファイルが選択されていません",
"file": "デバイスからアップロード", "file": "デバイスからアップロード",
"back": "戻る", "back": "戻る",
"wait": "お待ちください ...", "wait": "お待ちください ...",
@@ -223,10 +226,71 @@
"training": "トレーニング中", "training": "トレーニング中",
"completed": "トレーニング完了", "completed": "トレーニング完了",
"wait": "数分かかる場合があります", "wait": "数分かかる場合があります",
"tokenLimit": "トークン制限を超えています。より小さいドキュメントをアップロードしてください" "preparing": "アップロードを準備中",
"tokenLimit": "トークン制限を超えています。より小さいドキュメントをアップロードしてください",
"expandDetails": "アップロードの詳細を展開",
"collapseDetails": "アップロードの詳細を折りたたむ",
"dismiss": "アップロード通知を閉じる",
"uploadProgress": "アップロード進行状況 {{progress}}%",
"clear": "クリア"
}, },
"showAdvanced": "詳細オプションを表示", "showAdvanced": "詳細オプションを表示",
"hideAdvanced": "詳細オプションを非表示" "hideAdvanced": "詳細オプションを非表示",
"ingestors": {
"local_file": {
"label": "ファイルをアップロード",
"heading": "新しいドキュメントをアップロード"
},
"crawler": {
"label": "クローラー",
"heading": "Webクローラーでコンテンツを追加"
},
"url": {
"label": "リンク",
"heading": "URLからコンテンツを追加"
},
"github": {
"label": "GitHub",
"heading": "GitHubからコンテンツを追加"
},
"reddit": {
"label": "Reddit",
"heading": "Redditからコンテンツを追加"
},
"google_drive": {
"label": "Google Drive",
"heading": "Google Driveからアップロード"
}
},
"connectors": {
"auth": {
"connectedUser": "接続されたユーザー",
"authFailed": "認証に失敗しました",
"authUrlFailed": "認証URLの取得に失敗しました",
"popupBlocked": "認証ウィンドウを開けませんでした。ポップアップを許可してください。",
"authCancelled": "認証がキャンセルされました",
"connectedAs": "{{email}}として接続",
"disconnect": "切断"
},
"googleDrive": {
"connect": "Google Driveに接続",
"sessionExpired": "セッションが期限切れです。Google Driveに再接続してください。",
"sessionExpiredGeneric": "セッションが期限切れです。アカウントに再接続してください。",
"validateFailed": "セッションの検証に失敗しました。再接続してください。",
"noSession": "有効なセッションが見つかりません。Google Driveに再接続してください。",
"noAccessToken": "アクセストークンが利用できません。Google Driveに再接続してください。",
"pickerFailed": "ファイルピッカーを開けませんでした。もう一度お試しください。",
"selectedFiles": "選択されたファイル",
"selectFiles": "ファイルを選択",
"loading": "読み込み中...",
"noFilesSelected": "ファイルまたはフォルダが選択されていません",
"folders": "フォルダ",
"files": "ファイル",
"remove": "削除",
"folderAlt": "フォルダ",
"fileAlt": "ファイル"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "新しいAPIキーを作成", "label": "新しいAPIキーを作成",

View File

@@ -192,6 +192,9 @@
"uploadDoc": { "uploadDoc": {
"label": "Загрузить новый документ", "label": "Загрузить новый документ",
"select": "Выберите способ загрузки документа в DocsGPT", "select": "Выберите способ загрузки документа в DocsGPT",
"selectSource": "Выберите способ добавления источника",
"selectedFiles": "Выбранные файлы",
"noFilesSelected": "Файлы не выбраны",
"file": "Загрузить с устройства", "file": "Загрузить с устройства",
"back": "Назад", "back": "Назад",
"wait": "Пожалуйста, подождите...", "wait": "Пожалуйста, подождите...",
@@ -223,10 +226,71 @@
"training": "Идет обучение", "training": "Идет обучение",
"completed": "Обучение завершено", "completed": "Обучение завершено",
"wait": "Это может занять несколько минут", "wait": "Это может занять несколько минут",
"tokenLimit": "Превышен лимит токенов, рассмотрите возможность загрузки документа меньшего размера" "preparing": "Подготовка загрузки",
"tokenLimit": "Превышен лимит токенов, рассмотрите возможность загрузки документа меньшего размера",
"expandDetails": "Развернуть детали загрузки",
"collapseDetails": "Свернуть детали загрузки",
"dismiss": "Закрыть уведомление о загрузке",
"uploadProgress": "Прогресс загрузки {{progress}}%",
"clear": "Очистить"
}, },
"showAdvanced": "Показать расширенные настройки", "showAdvanced": "Показать расширенные настройки",
"hideAdvanced": "Скрыть расширенные настройки" "hideAdvanced": "Скрыть расширенные настройки",
"ingestors": {
"local_file": {
"label": "Загрузить файл",
"heading": "Загрузить новый документ"
},
"crawler": {
"label": "Краулер",
"heading": "Добавить контент с помощью веб-краулера"
},
"url": {
"label": "Ссылка",
"heading": "Добавить контент из URL"
},
"github": {
"label": "GitHub",
"heading": "Добавить контент из GitHub"
},
"reddit": {
"label": "Reddit",
"heading": "Добавить контент из Reddit"
},
"google_drive": {
"label": "Google Drive",
"heading": "Загрузить из Google Drive"
}
},
"connectors": {
"auth": {
"connectedUser": "Подключенный пользователь",
"authFailed": "Ошибка аутентификации",
"authUrlFailed": "Не удалось получить URL авторизации",
"popupBlocked": "Не удалось открыть окно аутентификации. Пожалуйста, разрешите всплывающие окна.",
"authCancelled": "Аутентификация отменена",
"connectedAs": "Подключен как {{email}}",
"disconnect": "Отключить"
},
"googleDrive": {
"connect": "Подключиться к Google Drive",
"sessionExpired": "Сеанс истек. Пожалуйста, переподключитесь к Google Drive.",
"sessionExpiredGeneric": "Сеанс истек. Пожалуйста, переподключите свою учетную запись.",
"validateFailed": "Не удалось проверить сеанс. Пожалуйста, переподключитесь.",
"noSession": "Действительный сеанс не найден. Пожалуйста, переподключитесь к Google Drive.",
"noAccessToken": "Токен доступа недоступен. Пожалуйста, переподключитесь к Google Drive.",
"pickerFailed": "Не удалось открыть средство выбора файлов. Пожалуйста, попробуйте еще раз.",
"selectedFiles": "Выбранные файлы",
"selectFiles": "Выбрать файлы",
"loading": "Загрузка...",
"noFilesSelected": "Файлы или папки не выбраны",
"folders": "Папки",
"files": "Файлы",
"remove": "Удалить",
"folderAlt": "Папка",
"fileAlt": "Файл"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "Создать новый API ключ", "label": "Создать новый API ключ",

View File

@@ -192,6 +192,9 @@
"uploadDoc": { "uploadDoc": {
"label": "上傳新文件", "label": "上傳新文件",
"select": "選擇如何將文件上傳到 DocsGPT", "select": "選擇如何將文件上傳到 DocsGPT",
"selectSource": "選擇新增來源的方式",
"selectedFiles": "已選擇的檔案",
"noFilesSelected": "未選擇檔案",
"file": "從檔案", "file": "從檔案",
"remote": "遠端", "remote": "遠端",
"back": "返回", "back": "返回",
@@ -223,10 +226,71 @@
"training": "正在訓練", "training": "正在訓練",
"completed": "訓練完成", "completed": "訓練完成",
"wait": "這可能需要幾分鐘", "wait": "這可能需要幾分鐘",
"tokenLimit": "超出令牌限制,請考慮上傳較小的文檔" "preparing": "準備上傳",
"tokenLimit": "超出令牌限制,請考慮上傳較小的文檔",
"expandDetails": "展開上傳詳情",
"collapseDetails": "摺疊上傳詳情",
"dismiss": "關閉上傳通知",
"uploadProgress": "上傳進度 {{progress}}%",
"clear": "清除"
}, },
"showAdvanced": "顯示進階選項", "showAdvanced": "顯示進階選項",
"hideAdvanced": "隱藏進階選項" "hideAdvanced": "隱藏進階選項",
"ingestors": {
"local_file": {
"label": "上傳檔案",
"heading": "上傳新文檔"
},
"crawler": {
"label": "爬蟲",
"heading": "使用網路爬蟲新增內容"
},
"url": {
"label": "連結",
"heading": "從URL新增內容"
},
"github": {
"label": "GitHub",
"heading": "從GitHub新增內容"
},
"reddit": {
"label": "Reddit",
"heading": "從Reddit新增內容"
},
"google_drive": {
"label": "Google Drive",
"heading": "從Google Drive上傳"
}
},
"connectors": {
"auth": {
"connectedUser": "已連接使用者",
"authFailed": "驗證失敗",
"authUrlFailed": "取得授權URL失敗",
"popupBlocked": "無法開啟驗證視窗。請允許彈出視窗。",
"authCancelled": "驗證已取消",
"connectedAs": "已連接為 {{email}}",
"disconnect": "中斷連接"
},
"googleDrive": {
"connect": "連接到 Google Drive",
"sessionExpired": "工作階段已過期。請重新連接到 Google Drive。",
"sessionExpiredGeneric": "工作階段已過期。請重新連接您的帳戶。",
"validateFailed": "驗證工作階段失敗。請重新連接。",
"noSession": "未找到有效工作階段。請重新連接到 Google Drive。",
"noAccessToken": "存取權杖不可用。請重新連接到 Google Drive。",
"pickerFailed": "無法開啟檔案選擇器。請重試。",
"selectedFiles": "已選擇的檔案",
"selectFiles": "選擇檔案",
"loading": "載入中...",
"noFilesSelected": "未選擇檔案或資料夾",
"folders": "資料夾",
"files": "檔案",
"remove": "移除",
"folderAlt": "資料夾",
"fileAlt": "檔案"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "建立新的 API 金鑰", "label": "建立新的 API 金鑰",

View File

@@ -192,6 +192,9 @@
"uploadDoc": { "uploadDoc": {
"label": "上传新文档", "label": "上传新文档",
"select": "选择如何将文档上传到 DocsGPT", "select": "选择如何将文档上传到 DocsGPT",
"selectSource": "选择添加源的方式",
"selectedFiles": "已选择的文件",
"noFilesSelected": "未选择文件",
"file": "从设备上传", "file": "从设备上传",
"back": "后退", "back": "后退",
"wait": "请稍等 ...", "wait": "请稍等 ...",
@@ -223,10 +226,71 @@
"training": "正在训练", "training": "正在训练",
"completed": "训练完成", "completed": "训练完成",
"wait": "这可能需要几分钟", "wait": "这可能需要几分钟",
"tokenLimit": "超出令牌限制,请考虑上传较小的文档" "preparing": "准备上传",
"tokenLimit": "超出令牌限制,请考虑上传较小的文档",
"expandDetails": "展开上传详情",
"collapseDetails": "折叠上传详情",
"dismiss": "关闭上传通知",
"uploadProgress": "上传进度 {{progress}}%",
"clear": "清除"
}, },
"showAdvanced": "显示高级选项", "showAdvanced": "显示高级选项",
"hideAdvanced": "隐藏高级选项" "hideAdvanced": "隐藏高级选项",
"ingestors": {
"local_file": {
"label": "上传文件",
"heading": "上传新文档"
},
"crawler": {
"label": "爬虫",
"heading": "使用网络爬虫添加内容"
},
"url": {
"label": "链接",
"heading": "从URL添加内容"
},
"github": {
"label": "GitHub",
"heading": "从GitHub添加内容"
},
"reddit": {
"label": "Reddit",
"heading": "从Reddit添加内容"
},
"google_drive": {
"label": "Google Drive",
"heading": "从Google Drive上传"
}
},
"connectors": {
"auth": {
"connectedUser": "已连接用户",
"authFailed": "身份验证失败",
"authUrlFailed": "获取授权URL失败",
"popupBlocked": "无法打开身份验证窗口。请允许弹出窗口。",
"authCancelled": "身份验证已取消",
"connectedAs": "已连接为 {{email}}",
"disconnect": "断开连接"
},
"googleDrive": {
"connect": "连接到 Google Drive",
"sessionExpired": "会话已过期。请重新连接到 Google Drive。",
"sessionExpiredGeneric": "会话已过期。请重新连接您的账户。",
"validateFailed": "验证会话失败。请重新连接。",
"noSession": "未找到有效会话。请重新连接到 Google Drive。",
"noAccessToken": "访问令牌不可用。请重新连接到 Google Drive。",
"pickerFailed": "无法打开文件选择器。请重试。",
"selectedFiles": "已选择的文件",
"selectFiles": "选择文件",
"loading": "加载中...",
"noFilesSelected": "未选择文件或文件夹",
"folders": "文件夹",
"files": "文件",
"remove": "删除",
"folderAlt": "文件夹",
"fileAlt": "文件"
}
}
}, },
"createAPIKey": { "createAPIKey": {
"label": "创建新的 API 密钥", "label": "创建新的 API 密钥",

View File

@@ -193,12 +193,12 @@ function Upload({
<div className="mb-3" {...getRootProps()}> <div className="mb-3" {...getRootProps()}>
<span className="text-purple-30 dark:text-silver inline-block rounded-3xl border border-[#7F7F82] bg-transparent px-4 py-2 font-medium hover:cursor-pointer"> <span className="text-purple-30 dark:text-silver inline-block rounded-3xl border border-[#7F7F82] bg-transparent px-4 py-2 font-medium hover:cursor-pointer">
<input type="button" {...getInputProps()} /> <input type="button" {...getInputProps()} />
Choose Files {t('modals.uploadDoc.choose')}
</span> </span>
</div> </div>
<div className="mt-4 max-w-full"> <div className="mt-4 max-w-full">
<p className="text-eerie-black dark:text-light-gray mb-[14px] text-[14px] font-medium"> <p className="text-eerie-black dark:text-light-gray mb-[14px] text-[14px] font-medium">
Selected Files {t('modals.uploadDoc.selectedFiles')}
</p> </p>
<div className="max-w-full overflow-hidden"> <div className="max-w-full overflow-hidden">
{files.map((file) => ( {files.map((file) => (
@@ -212,7 +212,7 @@ function Upload({
))} ))}
{files.length === 0 && ( {files.length === 0 && (
<p className="text-gray-6000 dark:text-light-gray text-[14px]"> <p className="text-gray-6000 dark:text-light-gray text-[14px]">
No files selected {t('modals.uploadDoc.noFilesSelected')}
</p> </p>
)} )}
</div> </div>
@@ -795,7 +795,7 @@ function Upload({
/> />
</div> </div>
<p className="font-inter self-start text-[13px] leading-[18px] font-semibold"> <p className="font-inter self-start text-[13px] leading-[18px] font-semibold">
{option.label} {t(`modals.uploadDoc.ingestors.${option.value}.label`)}
</p> </p>
</div> </div>
</div> </div>
@@ -812,7 +812,7 @@ function Upload({
<div className="flex w-full flex-col gap-6"> <div className="flex w-full flex-col gap-6">
{!ingestor.type && ( {!ingestor.type && (
<p className="font-inter text-left text-[20px] leading-[28px] font-semibold tracking-[0.15px] text-[#18181B] dark:text-[#ECECF1]"> <p className="font-inter text-left text-[20px] leading-[28px] font-semibold tracking-[0.15px] text-[#18181B] dark:text-[#ECECF1]">
Select the way to add your source {t('modals.uploadDoc.selectSource')}
</p> </p>
)} )}
@@ -830,12 +830,12 @@ function Upload({
alt="back" alt="back"
className="h-3 w-3 rotate-180 transform" className="h-3 w-3 rotate-180 transform"
/> />
<span>Back</span> <span>{t('modals.uploadDoc.back')}</span>
</button> </button>
<h2 className="font-inter text-[22px] leading-[28px] font-semibold tracking-[0.15px] text-black dark:text-[#E0E0E0]"> <h2 className="font-inter text-[22px] leading-[28px] font-semibold tracking-[0.15px] text-black dark:text-[#E0E0E0]">
{ingestor.type && {ingestor.type &&
getIngestorSchema(ingestor.type as IngestorType)?.heading} t(`modals.uploadDoc.ingestors.${ingestor.type}.heading`)}
</h2> </h2>
<Input <Input
@@ -849,7 +849,7 @@ function Upload({
})); }));
}} }}
borderVariant="thin" borderVariant="thin"
placeholder="Name" placeholder={t('modals.uploadDoc.name')}
required={true} required={true}
labelBgClassName="bg-white dark:bg-charleston-green-2" labelBgClassName="bg-white dark:bg-charleston-green-2"
className="w-full" className="w-full"