diff --git a/.github/workflows/check-pr-size.yml b/.github/workflows/check-pr-size.yml index 8b730e0..5b62fb2 100644 --- a/.github/workflows/check-pr-size.yml +++ b/.github/workflows/check-pr-size.yml @@ -6,6 +6,7 @@ on: jobs: check_pr_size: + if: false runs-on: ubuntu-latest timeout-minutes: 1 diff --git a/package-lock.json b/package-lock.json index df532c1..7c03ec7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@internxt/drive-desktop-core", - "version": "0.1.5", + "version": "0.1.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@internxt/drive-desktop-core", - "version": "0.1.5", + "version": "0.1.6", "license": "MIT", "dependencies": { "@internxt/sdk": "^1.11.10", diff --git a/package.json b/package.json index 7dafbcb..7a94b56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@internxt/drive-desktop-core", - "version": "0.1.5", + "version": "0.1.6", "author": "Internxt ", "license": "MIT", "files": [ diff --git a/sonar-project.properties b/sonar-project.properties index a9c4082..c067b6c 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,4 +1,5 @@ sonar.projectKey=internxt_drive-desktop-core sonar.organization=internxt sonar.javascript.lcov.reportPaths=./coverage/lcov.info -sonar.exclusions=**/*.test.ts,**/*.module.ts,./src/backend/index.ts +sonar.exclusions=**/*.test.ts,**/i18n/locales/*.ts +sonar.coverage.exclusions=**/*.module.ts,./src/backend/index.ts diff --git a/src/frontend/core/i18n/i18n.types.ts b/src/frontend/core/i18n/i18n.types.ts new file mode 100644 index 0000000..7df053c --- /dev/null +++ b/src/frontend/core/i18n/i18n.types.ts @@ -0,0 +1,22 @@ +import { en } from './locales/en'; + +export type Language = 'es' | 'en' | 'fr'; +export type Translation = typeof en; + +/** + * v2.6.0 Daniel Jiménez + * This type generates all possible paths from the translations. + * We set a maximum depth of 10 for a translation path. + */ +type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +type Paths = [D] extends [never] + ? never + : T extends object + ? { + [K in keyof T]-?: K extends string | number ? (T[K] extends object ? `${K}.${Paths & string}` : `${K}`) : never; + }[keyof T] + : never; + +export type TranslationPath = Paths; +export type TranslationArgs = Record; +export type TranslationFn = (path: TranslationPath, args?: Record) => string; diff --git a/src/frontend/core/i18n/index.ts b/src/frontend/core/i18n/index.ts new file mode 100644 index 0000000..2f41f30 --- /dev/null +++ b/src/frontend/core/i18n/index.ts @@ -0,0 +1,11 @@ +import { en } from './locales/en'; +import { es } from './locales/es'; +import { fr } from './locales/fr'; + +export { Language, TranslationFn, TranslationPath, TranslationArgs } from './i18n.types'; + +export const I18nModule = { + en, + es, + fr, +}; diff --git a/src/frontend/core/i18n/locales/en.ts b/src/frontend/core/i18n/locales/en.ts new file mode 100644 index 0000000..8a67fe7 --- /dev/null +++ b/src/frontend/core/i18n/locales/en.ts @@ -0,0 +1,446 @@ +export const en = { + login: { + email: { + section: 'Email address', + }, + password: { + section: 'Password', + placeholder: 'Password', + forgotten: 'Forgot your password?', + hide: 'Hide', + show: 'Show', + }, + action: { + login: 'Log in', + 'is-logging-in': 'Logging you in...', + }, + 'create-account': 'Create account', + '2fa': { + section: 'Authentication code', + description: 'You have configured two factor authentication, please enter the 6 digit code', + 'change-account': 'Change account', + 'wrong-code': 'Incorrect code, try again', + }, + error: { + 'empty-fields': 'Incorrect password or email', + }, + warning: { + 'no-internet': 'No internet connection', + }, + }, + onboarding: { + slides: { + welcome: { + title: 'Internxt Desktop', + description: + 'Welcome to Internxt!\n\nBack up your files with Drive, secure against malware with Antivirus, and optimize performance with Cleaner — all while keeping your privacy protected.', + 'take-tour': 'Take a tour', + }, + drive: { + title: 'Drive', + description: + 'Access all your files from the Internxt Drive folder in your {{platform_app}} sidebar.\n\nChoose to save space with online-only files, or keep essentials available offline — everything stays secure and in sync across your devices.', + }, + antivirus: { + title: 'Antivirus', + description: + 'Protect your device from malware and online threats.\n\nInternxt Antivirus keeps you safe with real-time scans and privacy-first security.', + }, + backups: { + title: 'Backup', + description: + "With Internxt's upgraded backup feature, you can now safely backup folders on the cloud in order to free up space locally. You can also adjust the backup frequency as you need.", + }, + cleaner: { + title: 'Cleaner', + description: + 'Free up space locally and optimize your device’s performance.\n\nOur cleaner finds and removes unnecessary files, so your device runs smoothly.', + }, + 'onboarding-completed': { + title: "You're all set, enjoy your privacy!", + 'desktop-ready': { + title: 'Internxt is ready', + description: 'Access your stored files from your {{platform_phrase}}’s sidebar', + }, + }, + }, + common: { + 'onboarding-progress': '{{current_slide}} of {{total_slides}}', + continue: 'Continue', + skip: 'Skip', + 'open-drive': 'Open Internxt', + 'platform-phrase': { + windows: 'file explorer', + }, + new: 'New', + }, + }, + widget: { + header: { + usage: { + of: 'of', + upgrade: 'Upgrade', + }, + dropdown: { + new: 'New', + preferences: 'Preferences', + sync: 'Sync', + issues: 'Issues', + support: 'Support', + antivirus: 'Antivirus', + logout: 'Log out', + quit: 'Quit', + 'logout-confirmation': { + title: 'Log out from this device?', + message: 'Internxt Drive will not show up without an account logged in.', + confirm: 'Log out', + cancel: 'Cancel', + }, + cleaner: 'Cleaner', + }, + }, + body: { + activity: { + operation: { + downloading: 'Downloading', + preparing: 'Preparing', + decrypting: 'Decrypting', + uploading: 'Uploading', + encrypting: 'Encrypting', + downloaded: 'Downloaded', + cancel_downloaded: 'Downloaded Cancel', + uploaded: 'Uploaded', + deleting: 'Moving to trash', + deleted: 'Moved to trash', + moved: 'Moved', + }, + }, + 'no-activity': { + title: 'There is no recent activity', + description: 'Information will show up here when changes are made to sync your local folder with Internxt Drive', + }, + upToDate: { + title: 'Your files are up to date', + subtitle: 'Sync activity will show up here', + }, + errors: { + sync: {}, + backups: { + 'folder-not-found': { + text: "Can't upload backup, missing folder", + action: 'View error', + }, + }, + }, + }, + footer: { + 'action-description': { + syncing: 'Syncing your files', + updated: 'Fully synced', + failed: 'Sync failed', + 'sync-pending': 'Sync pending', + }, + errors: { + lock: 'Sync locked by other device', + offline: 'Not connected to the internet', + }, + }, + 'sync-error': { + title: "Can't get remote content", + message: 'We are having issues retrieving your content from the cloud, please try again', + button: 'Try again', + }, + banners: { + 'discover-backups': { + title: 'INTERNXT BACKUPS', + body: 'Keep a lifesaver copy of your most important folders and files.', + action: 'Backup this device', + }, + }, + }, + settings: { + header: { + section: { + GENERAL: 'general', + ACCOUNT: 'account', + BACKUPS: 'backups', + ANTIVIRUS: 'Antivirus', + CLEANER: 'Cleaner', + }, + }, + general: { + language: { + label: 'Language', + options: { + es: 'Español (Spanish)', + en: 'English (English)', + fr: 'Français (French)', + }, + }, + theme: { + label: 'Appearance', + options: { + system: 'System', + light: 'Light', + dark: 'Dark', + }, + }, + + device: { + section: 'Device name', + action: { + edit: 'Edit', + cancel: 'Cancel', + save: 'Save', + }, + }, + 'auto-startup': 'Start Internxt on system startup', + sync: { + folder: 'Internxt Folder', + 'change-folder': 'Change folder', + }, + 'app-info': { + 'open-logs': 'Open logs', + more: 'Learn more about Internxt', + }, + }, + account: { + logout: 'Log out', + usage: { + display: 'Used {{used}} of {{total}}', + upgrade: 'Upgrade', + change: 'Change', + plan: 'Current plan', + free: 'Free', + loadError: { + title: "Couldn't fetch your usage details", + action: 'Retry', + }, + current: { + used: 'Used', + of: 'of', + 'in-use': 'in use', + }, + full: { + title: 'Your storage is full', + subtitle: "You can't upload, sync, or backup files. Upgrade now your plan or remove files to save up space.", + }, + }, + }, + backups: { + title: 'Backup folders', + 'selected-folder_one': '{{count}} folder', + 'selected-folder_other': '{{count}} folders', + 'add-folders': 'Click + to select the folders\n you want to back up', + activate: 'Back up your folders and files', + 'view-backups': 'Browse Backups', + 'selected-folders-title': 'Selected folders', + 'select-folders': 'Change folders', + 'last-backup-had-issues': 'Last backup had some issues', + 'see-issues': 'See issues', + 'backing-up': 'Backing up...', + action: { + start: 'Backup now', + stop: 'Stop backup', + running: 'Backup in progress {{progress}}', + 'last-run': 'Last updated', + }, + frequency: { + title: 'Upload frequency', + options: { + '1h': 'Every hour', + '6h': 'Every 6 hours', + '12h': 'Every 12 hours', + '24h': 'Every day', + manually: 'Backup manually', + }, + warning: "Folders won't automatically backup until you click 'Backup now'. This mode is not recommended.", + }, + folders: { + 'no-folders': 'empty folder, no folder available', + 'no-folders-to-download': 'No folders available for download', + save: 'Save', + cancel: 'Cancel', + error: 'We could not load your backups', + }, + delete: { + title: 'Delete backup', + explanation: 'This backup will be removed from the cloud, all folders and files will remain in this computer', + action: 'Delete backup', + 'deletion-modal': { + title: 'Delete backup?', + explanation: 'This backup will be removed from the cloud permanently, all folders and files will remain in this computer.', + 'explanation-2': 'This action cannot be undone.', + confirm: 'Yes, delete', + cancel: 'Cancel', + }, + }, + stop: { + modal: { + title: 'Stop ongoing backup', + explanation: 'There are still files that have not yet been uploaded. Stop backup anyway?', + 'explanation-2': '', + confirm: 'Stop backup', + cancel: 'Cancel', + }, + }, + }, + antivirus: { + featureLocked: { + title: 'Feature locked', + subtitle: 'Please upgrade your plan to use this feature.', + action: 'Upgrade', + }, + errorState: { + title: 'Something went wrong while scanning the directory', + button: 'Try again', + }, + scanOptions: { + stopScan: 'Stop scan', + systemScan: { + text: 'Antivirus system scan', + action: 'Start scan', + }, + customScan: { + text: 'Antivirus custom scan', + action: 'Choose', + selector: { + files: 'Files', + folders: 'Folders', + }, + }, + removeMalware: { + actions: { + cancel: 'Cancel', + remove: 'Remove', + }, + actionRequired: { + title: 'Action required', + description: + 'Removing the malware will also permanently delete the folder from your storage to protect your device. This action cannot be undone.', + confirmToContinue: 'Please confirm to continue.', + }, + securityWarning: { + title: 'Security warning', + description: 'Malware is still present, and your device is at risk.', + confirmToCancel: 'Are you sure you want to cancel?', + }, + }, + }, + scanProcess: { + countingFiles: 'Counting files...', + scanning: 'Scanning...', + scannedFiles: 'Scanned files', + detectedFiles: 'Detected files', + errorWhileScanning: 'An error occurred while scanning the items. Please try again.', + noFilesFound: { + title: 'No threats were found', + subtitle: 'No further actions are necessary', + }, + malwareFound: { + title: 'Malware detected', + subtitle: 'Please review and remove threats.', + action: 'Remove malware', + }, + scanAgain: 'Scan again', + }, + filesContainingMalwareModal: { + title: 'Files containing malware', + selectedItems: 'Selected {{selectedFiles}} out of {{totalFiles}}', + selectAll: 'Select all', + actions: { + cancel: 'Cancel', + remove: 'Remove', + }, + }, + }, + cleaner: { + selectAllCheckbox: 'Select all', + mainView: { + cleanup: 'Clean Up', + }, + generateReportView: { + title: 'No scan yet', + description: 'Scan your system to find files you can safely remove and free up space.', + generateReport: 'Run scan', + }, + loadingView: { + title: 'Please wait a moment.', + description: 'We are generating your report...', + }, + sizeIndicatorView: { + selectCategory: 'Select a category to', + previewContent: 'preview content', + saveUpTo: 'Save up to', + ofYourSpace: 'of your space', + }, + cleanupConfirmDialogView: { + title: 'Confirm cleanup', + description: + 'This action will permanently delete the selected files from your device. This cannot be undone. Please, confirm to continue.', + cancelButton: 'Cancel', + confirmButton: 'Delete files', + }, + cleaningView: { + cleaningProcess: { + title: 'Cleaning...', + stopCleanButton: 'Stop clean', + deletedFiles: 'Deleted files', + freeSpaceGained: 'Free space gained', + }, + cleaningFinished: { + title: 'Your device is clean', + subtitle: 'No further actions are necessary', + finish: 'Finish', + }, + }, + }, + }, + issues: { + title: 'Issues', + tabs: { + sync: 'Sync', + backups: 'Backups', + antivirus: 'Antivirus', + general: 'General', + }, + 'no-issues': 'No issues found', + actions: { + 'select-folder': 'Select folder', + 'find-folder': 'Find folder', + 'try-again': 'Try again', + }, + 'report-modal': { + actions: { + close: 'Close', + cancel: 'Cancel', + report: 'Report', + send: 'Send', + }, + 'help-url': 'To get help visit', + report: 'You can also send a report about this error.', + 'user-comments': 'Comments', + 'include-logs': 'Include the logs of this sync process for debug purposes', + }, + errors: { + ABORTED: 'Aborted', + CREATE_FOLDER_FAILED: 'Failed to create folder', + DELETE_ERROR: 'Cannot delete item', + FILE_MODIFIED: 'File modified while uploading', + FILE_SIZE_TOO_BIG: 'File size too big (max 20GB)', + FOLDER_ACCESS_DENIED: 'The app does not have permission to access this folder', + FOLDER_DOES_NOT_EXIST: 'Folder does not exist', + INVALID_WINDOWS_NAME: String.raw`Windows does not allow names that include the characters \ / : * ? " < > |`, + NETWORK_CONNECTIVITY_ERROR: 'Network connectivity error.', + NOT_ENOUGH_SPACE: 'You have not enough space to complete the operation', + PARENT_FOLDER_DOES_NOT_EXIST: 'Parent folder does not exist', + ROOT_FOLDER_DOES_NOT_EXIST: 'Root folder does not exist', + SERVER_INTERNAL_ERROR: 'Server internal error.', + UNKNOWN_DEVICE_NAME: "Could not retrieve your device's name", + WEBSOCKET_CONNECTION_ERROR: 'WebSocket connection error', + }, + }, + common: { + cancel: 'Cancel', + }, +}; diff --git a/src/frontend/core/i18n/locales/es.ts b/src/frontend/core/i18n/locales/es.ts new file mode 100644 index 0000000..5bba506 --- /dev/null +++ b/src/frontend/core/i18n/locales/es.ts @@ -0,0 +1,450 @@ +import { Translation } from '../i18n.types'; + +export const es: Translation = { + login: { + email: { + section: 'Correo electrónico', + }, + password: { + section: 'Contraseña', + placeholder: 'Contraseña', + forgotten: '¿Has olvidado tu contraseña?', + hide: 'Ocultar', + show: 'Mostrar', + }, + action: { + login: 'Iniciar sesión', + 'is-logging-in': 'Iniciando sesión...', + }, + 'create-account': 'Crear cuenta', + '2fa': { + section: 'Código de autenticación', + description: 'Has configurado la autenticación en dos pasos, por favor introduce el código de 6 dígitos', + 'change-account': 'Cambiar cuenta', + 'wrong-code': 'Código incorrecto, inténtalo de nuevo', + }, + error: { + 'empty-fields': 'Contraseña o correo electrónico incorrectos', + }, + warning: { + 'no-internet': 'Sin conexión a internet', + }, + }, + onboarding: { + slides: { + welcome: { + title: 'Internxt Desktop', + description: + '¡Bienvenido a Internxt!\n\nHaz copias de seguridad de tus archivos con Drive, protégelos contra malware con Antivirus y optimiza el rendimiento con Cleaner — todo mientras mantienes tu privacidad protegida.', + 'take-tour': 'Hacer recorrido', + }, + drive: { + title: 'Drive', + description: + 'Accede a todos tus archivos desde la carpeta de Internxt Drive en la barra lateral de {{platform_app}}.\n\nElige ahorrar espacio con archivos disponibles solo en línea o mantener los esenciales sin conexión — todo permanece seguro y sincronizado en todos tus dispositivos.', + }, + antivirus: { + title: 'Antivirus', + description: + 'Protege tu dispositivo contra el malware y las amenazas en línea.\n\nInternxt Antivirus te mantiene seguro con análisis en tiempo real y una seguridad que prioriza tu privacidad.', + }, + backups: { + title: 'Backup', + description: + 'Con la función de copia de seguridad mejorada de Internxt, ahora puedes hacer copias seguras de tus carpetas en la nube para liberar espacio localmente.\n\nTambién puedes ajustar la frecuencia de las copias de seguridad según tus necesidades.', + }, + cleaner: { + title: 'Cleaner', + description: + 'Libera espacio localmente y optimiza el rendimiento de tu dispositivo.\n\nNuestro limpiador detecta y elimina archivos innecesarios para que tu dispositivo funcione sin problemas.', + }, + 'onboarding-completed': { + title: 'Ya está todo listo, ¡disfruta de tu privacidad!', + 'desktop-ready': { + title: 'Internxt está listo', + description: 'Accede a tus archivos almacenados desde la barra lateral de tu {{platform_phrase}}.', + }, + }, + }, + common: { + 'onboarding-progress': '{{current_slide}} de {{total_slides}}', + continue: 'Continuar', + 'open-drive': 'Abrir Internxt', + skip: 'Saltar', + 'platform-phrase': { + windows: 'explorador de archivos', + }, + new: 'Nuevo', + }, + }, + widget: { + header: { + usage: { + of: 'de', + upgrade: 'Comprar espacio', + }, + dropdown: { + new: 'Nuevo', + preferences: 'Preferencias', + sync: 'Sincronizar', + issues: 'Lista de errores', + support: 'Ayuda', + antivirus: 'Antivirus', + logout: 'Cerrar sesión', + quit: 'Salir', + 'logout-confirmation': { + title: '¿Cerrar sesión en este dispositivo?', + message: 'Internxt no se mostrará sin una cuenta iniciada.', + confirm: 'Cerrar sesión', + cancel: 'Cancelar', + }, + cleaner: 'Cleaner', + }, + }, + body: { + activity: { + operation: { + downloading: 'Descargando', + preparing: 'Preparando', + decrypting: 'Desencriptando', + uploading: 'Subiendo', + encrypting: 'Encriptando', + downloaded: 'Descargado', + cancel_downloaded: 'Descarga Cancelada', + uploaded: 'Subido', + deleting: 'Moviendo a la papelera', + deleted: 'Movido a la papelera', + moved: 'Movido', + }, + }, + 'no-activity': { + title: 'No hay actividad reciente', + description: 'La información aparecerá aquí cuando hagas cambios, para sincronizar tu carpeta local con Internxt Drive', + }, + upToDate: { + title: 'Tus archivos están actualizados', + subtitle: 'La actividad de sincronización se mostrará aquí', + }, + errors: { + sync: {}, + backups: { + 'folder-not-found': { + text: 'No se pudo realizar la copia, no se encuentra la carpeta', + action: 'Ver error', + }, + }, + }, + }, + footer: { + 'action-description': { + syncing: 'Sincronizando tus archivos', + updated: 'Sincronizado', + failed: 'Sincronización fallida', + 'sync-pending': 'Sincronización pendiente', + }, + errors: { + lock: 'Sincronización bloqueada por otro dispositivo', + offline: 'No hay conexión a internet', + }, + }, + 'sync-error': { + title: 'No se puede acceder al contenido', + message: 'Parece que hay problemas para obtener el contenido de la nube, por favor inténtalo de nuevo', + button: 'Reintentar', + }, + banners: { + 'discover-backups': { + title: ' COPIAS DE SEGURIDAD DE INTERNXT', + body: 'Mantén una copia de seguridad de tus carpetas y archivos más importantes.', + action: 'Hacer copia', + }, + }, + }, + settings: { + header: { + section: { + GENERAL: 'General', + ACCOUNT: 'Cuenta', + BACKUPS: 'Backups', + ANTIVIRUS: 'Antivirus', + CLEANER: 'Cleaner', + }, + }, + general: { + language: { + label: 'Idioma', + options: { + es: 'Español (Español)', + en: 'English (Inglés)', + fr: 'Français (Francés)', + }, + }, + theme: { + label: 'Apariencia', + options: { + system: 'Sistema', + light: 'Claro', + dark: 'Oscuro', + }, + }, + device: { + section: 'Nombre del dispositivo', + action: { + edit: 'Editar', + cancel: 'Cancelar', + save: 'Guardar', + }, + }, + 'auto-startup': 'Iniciar Internxt al arrancar el sistema', + sync: { + folder: 'Carpeta Internxt', + 'change-folder': 'Cambiar carpeta', + }, + 'app-info': { + 'open-logs': 'Abrir registros', + more: 'Más información sobre Internxt', + }, + }, + account: { + logout: 'Cerrar sesión', + usage: { + display: 'Usado {{used}} de {{total}}', + upgrade: 'Comprar espacio', + change: 'Cambiar', + plan: 'Plan actual', + free: 'Gratis', + loadError: { + title: 'No se han podido obtener tus datos de uso', + action: 'Reintentar', + }, + current: { + used: 'usado', + of: 'de', + 'in-use': 'usado', + }, + full: { + title: 'Tu almacenamiento está lleno', + subtitle: + 'No puedes subir, sincronizar ni hacer copias de seguridad de archivos. Amplía ahora tu plan o elimina archivos para ahorrar espacio.', + }, + }, + }, + backups: { + title: 'Carpetas de copia de seguridad', + 'add-folders': 'Haz clic en + para hacer una copia de seguridad de tus carpetas', + 'selected-folder_one': '{{count}} carpeta', + 'selected-folder_other': '{{count}} carpetas', + activate: 'Hacer copia de seguridad de tus carpetas', + 'view-backups': 'Explorar backups', + 'selected-folders-title': 'Carpetas seleccionadas', + 'select-folders': 'Cambiar carpetas', + 'last-backup-had-issues': 'La última copia de seguridad tuvo algunos problemas', + 'see-issues': 'Ver problemas', + 'backing-up': 'Haciendo la copia', + action: { + start: 'Hacer copia', + stop: 'Stop backup', + running: 'Subiendo backup {{progress}}', + 'last-run': 'Última ejecución', + }, + frequency: { + title: 'Frecuencia de subida', + options: { + '1h': 'Cada hora', + '6h': 'Cada 6 horas', + '12h': 'Cada 12 horas', + '24h': 'Cada día', + manually: 'Manual', + }, + warning: + "Las carpetas no se respaldarán automáticamente hasta que haga clic en 'Copia de seguridad ahora'. Este modo no se recomienda.", + }, + folders: { + 'no-folders': 'No hay carpetas seleccionadas', + 'no-folders-to-download': 'No hay carpetas para descargar', + save: 'Guardar', + cancel: 'Cancelar', + error: 'No pudimos encontrar la carpeta seleccionada', + }, + delete: { + title: 'Eliminar copia de seguridad', + explanation: 'Esta copia de seguridad se eliminará de la nube, todas las carpetas y archivos permanecerán en este ordenador', + action: 'Eliminar copia de seguridad', + 'deletion-modal': { + title: 'Borrar copia de seguridad?', + explanation: + 'Esta copia de seguridad se eliminará permanentemente de la nube, todas las carpetas y archivos permanecerán en este ordenador.', + 'explanation-2': 'Esta acción no se puede deshacer.', + confirm: 'Sí, eliminar', + cancel: 'Cancelar', + }, + }, + stop: { + modal: { + title: 'Detener copia de seguridad en curso', + explanation: 'Todavía hay archivos que no se han subido. ¿Detener la copia de seguridad de todos modos?', + 'explanation-2': '', + confirm: 'Detener', + cancel: 'Cancelar', + }, + }, + }, + antivirus: { + featureLocked: { + title: 'Función bloqueada', + subtitle: 'Por favor, actualiza tu plan para usar esta función.', + action: 'Actualizar', + }, + errorState: { + title: 'Algo salió mal al escanear el directorio', + button: 'Intentar de nuevo', + }, + scanOptions: { + stopScan: 'Detener escaneo', + systemScan: { + text: 'Escaneo del sistema antivirus', + action: 'Iniciar escaneo', + }, + customScan: { + text: 'Escaneo personalizado del antivirus', + action: 'Elegir', + selector: { + files: 'Archivos', + folders: 'Carpetas', + }, + }, + removeMalware: { + actions: { + cancel: 'Cancelar', + remove: 'Eliminar', + }, + actionRequired: { + title: 'Acción requerida', + description: + 'Al eliminar el malware, también se eliminará permanentemente la carpeta de tu almacenamiento para proteger tu dispositivo. Esta acción no se puede deshacer.', + confirmToContinue: 'Confirma para continuar.', + }, + securityWarning: { + title: 'Advertencia de seguridad', + description: 'El malware sigue presente y tu dispositivo está en riesgo.', + confirmToCancel: '¿Estás seguro de que deseas cancelar?', + }, + }, + }, + scanProcess: { + countingFiles: 'Contando archivos...', + scanning: 'Escaneando...', + scannedFiles: 'Archivos escaneados', + detectedFiles: 'Archivos detectados', + errorWhileScanning: 'Ocurrió un error al escanear los elementos. Por favor, intenta nuevamente.', + noFilesFound: { + title: 'No se encontraron amenazas', + subtitle: 'No es necesario realizar más acciones', + }, + malwareFound: { + title: 'Malware detectado', + subtitle: 'Por favor, revisa y elimina las amenazas.', + action: 'Eliminar malware', + }, + scanAgain: 'Escanear nuevamente', + }, + filesContainingMalwareModal: { + title: 'Archivos que contienen malware', + selectedItems: 'Seleccionados {{selectedFiles}} de {{totalFiles}}', + selectAll: 'Seleccionar todo', + actions: { + cancel: 'Cancelar', + remove: 'Eliminar', + }, + }, + }, + cleaner: { + selectAllCheckbox: 'Seleccionar todo', + mainView: { + cleanup: 'Limpiar', + }, + generateReportView: { + title: 'Ningún escaneo todavía', + description: 'Escanee su sistema para encontrar archivos que pueda eliminar de forma segura y liberar espacio.', + generateReport: 'Ejecutar escaneo', + }, + loadingView: { + title: 'Espera un momento', + description: 'Estamos generando tu informe...', + }, + sizeIndicatorView: { + selectCategory: 'Seleccione una categoría para', + previewContent: 'obtener una vista previa del contenido', + saveUpTo: 'Ahorra hasta', + ofYourSpace: 'de tu espacio', + }, + cleanupConfirmDialogView: { + title: 'Confirmar borrado', + description: + 'Esta acción eliminará permanentemente los archivos seleccionados de tu dispositivo. Esta acción no se puede deshacer. Confirme para continuar.', + cancelButton: 'Cancelar', + confirmButton: 'Eliminar archivos', + }, + cleaningView: { + cleaningProcess: { + title: 'Limpiando...', + stopCleanButton: 'Detener limpieza', + deletedFiles: 'Archivos eliminados', + freeSpaceGained: 'Espacio libre ganado', + }, + cleaningFinished: { + title: 'Tu dispositivo está limpio', + subtitle: 'No es necesario realizar ninguna otra acción', + finish: 'Finalizar', + }, + }, + }, + }, + issues: { + title: 'Lista de errores', + tabs: { + sync: 'Sincronización', + backups: 'Copias de seguridad', + general: 'General', + antivirus: 'Antivirus', + }, + 'no-issues': 'No se han encontrado errores', + actions: { + 'select-folder': 'Seleccionar carpeta', + 'find-folder': 'Buscar la carpeta', + 'try-again': 'Volver a intentar', + }, + 'report-modal': { + actions: { + close: 'Cerrar', + cancel: 'Cancelar', + report: 'Informar', + send: 'Enviar', + }, + 'help-url': 'Para obtener ayuda, visita', + report: 'También puedes enviar un informe sobre este error', + 'user-comments': 'Comentarios', + 'include-logs': 'Incluir los registros de este proceso de sincronización con fines de solucionar el error', + }, + errors: { + ABORTED: 'Abortado', + CREATE_FOLDER_FAILED: 'Error al crear la carpeta', + DELETE_ERROR: 'No se pudo eliminar el elemento', + FILE_MODIFIED: 'Archivo modificado durante la subida', + FILE_SIZE_TOO_BIG: 'Archivo es demasiado grande (máximo 20GB)', + FOLDER_ACCESS_DENIED: 'La app no tiene permiso para acceder a esta carpeta', + FOLDER_DOES_NOT_EXIST: 'Carpeta no existe', + INVALID_WINDOWS_NAME: String.raw`Windows no permite nombres que incluyen los caracteres \ / : * ? " < > |`, + NETWORK_CONNECTIVITY_ERROR: 'Error de conectividad de red', + NOT_ENOUGH_SPACE: 'No tienes suficiente espacio para completar la operación', + PARENT_FOLDER_DOES_NOT_EXIST: 'Carpeta padre no existe', + ROOT_FOLDER_DOES_NOT_EXIST: 'Carpeta raíz no existe', + SERVER_INTERNAL_ERROR: 'Error interno del servidor', + UNKNOWN_DEVICE_NAME: 'No se pudo obtener el nombre de tu dispositivo', + WEBSOCKET_CONNECTION_ERROR: 'Error de conexión WebSocket', + }, + }, + common: { + cancel: 'Cancelar', + }, +}; diff --git a/src/frontend/core/i18n/locales/fr.ts b/src/frontend/core/i18n/locales/fr.ts new file mode 100644 index 0000000..b80939f --- /dev/null +++ b/src/frontend/core/i18n/locales/fr.ts @@ -0,0 +1,452 @@ +import { Translation } from '../i18n.types'; + +export const fr: Translation = { + login: { + email: { + section: 'Adresse électronique', + }, + password: { + section: 'Mot de passe', + placeholder: 'Mot de passe', + forgotten: 'Vous avez oublié votre mot de passe?', + hide: 'Cacher', + show: 'Afficher', + }, + action: { + login: "S'identifier", + 'is-logging-in': 'Se connecter...', + }, + 'create-account': 'Créer un compte', + '2fa': { + section: "Code d'authentification", + description: "Vous avez configuré l'authentification en deux étapes (2FA), veuillez saisir le code à 6 chiffres", + 'change-account': 'Changer de compte', + 'wrong-code': 'Code incorrect, veuillez réessayer', + }, + error: { + 'empty-fields': 'Mot de passe ou courriel incorrect', + }, + warning: { + 'no-internet': 'Pas de connexion internet', + }, + }, + onboarding: { + slides: { + welcome: { + title: 'Internxt Desktop', + description: + 'Bienvenue dans Internxt!\n\nSauvegardez vos fichiers avec Drive, protégez-les contre les logiciels malveillants avec Antivirus et optimisez les performances avec Cleaner — tout en préservant votre vie privée.', + 'take-tour': 'Visite guidée', + }, + drive: { + title: 'Drive', + description: + 'Accédez à tous vos fichiers depuis le dossier Internxt Drive dans la barre latérale de {{platform_app}}.\n\nChoisissez d’économiser de l’espace avec des fichiers disponibles uniquement en ligne, ou gardez l’essentiel accessible hors ligne — tout reste sécurisé et synchronisé sur tous vos appareils.', + }, + antivirus: { + title: 'Antivirus', + description: + 'Protégez votre appareil contre les logiciels malveillants et les menaces en ligne.\n\nInternxt Antivirus vous protège grâce à des analyses en temps réel et une sécurité axée sur la confidentialité.', + }, + backups: { + title: 'Backup', + description: + 'Avec la fonction de sauvegarde améliorée d’Internxt, vous pouvez désormais sauvegarder vos dossiers en toute sécurité sur le cloud afin de libérer de l’espace localement.\n\nVous pouvez également ajuster la fréquence des sauvegardes selon vos besoins.', + }, + cleaner: { + title: 'Cleaner', + description: + 'Libérez de l’espace localement et optimisez les performances de votre appareil.\n\nNotre nettoyeur détecte et supprime les fichiers inutiles afin que votre appareil fonctionne sans encombre.', + }, + 'onboarding-completed': { + title: 'Vous êtes prêt, profitez de votre vie privée !', + 'desktop-ready': { + title: 'Internxt est prêt', + description: 'Accédez à vos fichiers stockés depuis la barre latérale de votre {{platform_phrase}}.', + }, + }, + }, + common: { + 'onboarding-progress': '{{current_slide}} de {{total_slides}}', + 'open-drive': 'Ouvrir Internxt', + continue: 'Continuer', + skip: 'Sauter', + 'platform-phrase': { + windows: 'navigateur de fichiers', + }, + new: 'Nouveau', + }, + }, + widget: { + header: { + usage: { + of: 'de', + upgrade: 'Acheter maintenant', + }, + dropdown: { + new: 'Nouveau', + preferences: 'Préférences', + sync: 'Synchroniser', + issues: "Liste d'erreurs", + support: 'Aide', + antivirus: 'Antivirus', + logout: 'Déconnecter', + quit: 'Fermer', + 'logout-confirmation': { + title: 'Se déconnecter de cet appareil?', + message: "Internxt ne s'affichera pas sans un compte connecté.", + confirm: 'Se déconnecter', + cancel: 'Annuler', + }, + cleaner: 'Cleaner', + }, + }, + body: { + activity: { + operation: { + downloading: 'Téléchargement', + preparing: 'Préparation', + decrypting: 'Décryptage', + uploading: 'téléchargement', + encrypting: 'Encryptage', + downloaded: 'Téléchargé', + cancel_downloaded: 'Télécharger Annulé', + uploaded: 'Téléchargé', + deleting: 'Déplacement vers les poubelles', + deleted: 'Déplacé vers la poubelle', + moved: 'Déplacé', + }, + }, + 'no-activity': { + title: 'Aucune activité récente', + description: + 'Les informations apparaîtront ici lorsque vous effectuerez des modifications, pour synchroniser votre dossier local avec Internxt', + }, + upToDate: { + title: 'Vos fichiers sont à jour', + subtitle: "L'activité de synchronisation s'affichera ici", + }, + errors: { + sync: {}, + backups: { + 'folder-not-found': { + text: 'Impossible de copier, dossier non trouvé', + action: "Afficher l'erreur", + }, + }, + }, + }, + footer: { + 'action-description': { + syncing: 'Synchronisation de vos fichiers', + updated: 'Synchronisation complète', + failed: 'Échec de la synchronisation', + 'sync-pending': 'Synchronisation en attente', + }, + errors: { + lock: 'Synchronisation bloquée par un autre dispositif', + offline: 'Non connecté à Internet', + }, + }, + 'sync-error': { + title: "Impossible d'obtenir le contenu à distance", + message: 'Nous avons des problèmes pour récupérer votre contenu depuis le nuage, veuillez réessayer ', + button: 'Essayez à nouveau ', + }, + banners: { + 'discover-backups': { + title: 'INTERNXT SAUVEGARDES', + body: 'Gardez une copie de secours de vos dossiers et fichiers les plus importants.', + action: 'Sauvegarder', + }, + }, + }, + settings: { + header: { + section: { + GENERAL: 'Général', + ACCOUNT: 'Compte', + BACKUPS: 'Sauvegardes', + ANTIVIRUS: 'Antivirus', + CLEANER: 'Cleaner', + }, + }, + general: { + language: { + label: 'Langue', + options: { + es: 'Español (Espagnole)', + en: 'English (Anglaise)', + fr: 'Français (Français)', + }, + }, + theme: { + label: 'Apparence', + options: { + system: 'Système', + light: 'Lumière', + dark: 'Sombre', + }, + }, + device: { + section: 'Nom du dispositif', + action: { + edit: 'Editer', + cancel: 'Annuler', + save: 'Enregistrer', + }, + }, + 'auto-startup': 'Démarrer Internxt au démarrage du système', + sync: { + folder: 'Dossier Internxt', + 'change-folder': 'Changer de dossier', + }, + 'app-info': { + 'open-logs': 'Ouvrir les registres', + more: "Plus d'informations sur Internxt", + }, + }, + account: { + logout: 'Déconnecter', + usage: { + display: 'Utilisé {{used}} sur {{total}}', + upgrade: 'Acheter', + change: 'Changement', + plan: 'Plan actuel', + free: 'Gratuit', + loadError: { + title: "Impossible d'obtenir les détails de votre utilisation", + action: 'Réessayer', + }, + current: { + used: 'utilisés', + of: 'de', + 'in-use': 'utilisé', + }, + full: { + title: 'Votre espace de stockage est plein', + subtitle: + "Vous ne pouvez pas télécharger, synchroniser ou sauvegarder des fichiers. Mettez votre forfait à niveau ou supprimez des fichiers pour économiser de l'espace.", + }, + }, + }, + backups: { + title: 'Dossiers de sauvegarde', + 'add-folders': 'Cliquez sur + pour sélectionner les dossiers que vous souhaitez sauvegarder', + 'selected-folder_one': '{{count}} dossier', + 'selected-folder_other': '{{count}} dossiers', + activate: 'Sauvegarder vos dossiers', + 'view-backups': 'Parcourir les backups', + 'selected-folders-title': 'Dossiers sélectionnés', + 'select-folders': 'Changer les dossiers', + 'last-backup-had-issues': 'La dernière sauvegarde a rencontré quelques problèmes', + 'see-issues': 'Voir des problèmes', + 'backing-up': 'Sauvegarde...', + action: { + start: 'Faire une copie ', + stop: 'Arrêter la sauvegarde', + running: 'Sauvegarde en cours {{progress}}', + 'last-run': 'Dernière exécution', + }, + frequency: { + title: 'Fréquence de téléchargement', + options: { + '1h': 'Toutes les heures', + '6h': 'Toutes les 6 heures', + '12h': 'Toutes les 12 heures', + '24h': 'Tous les jours', + manually: 'Manuellement', + }, + warning: + 'Les dossiers ne seront pas automatiquement sauvegardés tant que vous n’aurez pas cliqué sur « Sauvegarder maintenant ». Ce mode n’est pas recommandé.', + }, + folders: { + 'no-folders': 'Pas encore de sauvegardes', + 'no-folders-to-download': 'Pas de dossiers à télécharger', + save: 'Sauvegarder', + cancel: 'Annuler', + error: 'Nous n’avons pas trouvé le dossier sélectionné', + }, + delete: { + title: 'Supprimer la sauvegarde', + explanation: 'Cette sauvegarde sera supprimée du cloud, tous les dossiers et fichiers resteront sur cet ordinateur', + action: 'Supprimer la sauvegarde', + 'deletion-modal': { + title: 'Arrêter la sauvegarde de ', + explanation: + 'Cette sauvegarde sera supprimée définitivement du cloud, tous les dossiers et fichiers resteront sur cet ordinateur.', + 'explanation-2': 'Cette action est irréversible.', + confirm: 'Oui, supprimer', + cancel: 'Annuler', + }, + }, + stop: { + modal: { + title: 'Arrêter la sauvegarde en cours', + explanation: "Il reste encore des fichiers qui n'ont pas été téléchargés. Arrêter la sauvegarde quand même?", + 'explanation-2': '', + confirm: 'Arrêter la sauvegarde', + cancel: 'Annuler', + }, + }, + }, + antivirus: { + featureLocked: { + title: 'Fonction verrouillée', + subtitle: 'Veuillez mettre à niveau votre plan pour utiliser cette fonctionnalité.', + action: 'Mettre à niveau', + }, + errorState: { + title: "Une erreur s'est produite lors de l'analyse du répertoire", + button: 'Réessayer', + }, + scanOptions: { + stopScan: "Arrêter l'analyse", + systemScan: { + text: 'Analyse du système antivirus', + action: "Démarrer l'analyse", + }, + customScan: { + text: "Analyse personnalisée de l'antivirus", + action: 'Choisir', + selector: { + files: 'Fichiers', + folders: 'Dossiers', + }, + }, + removeMalware: { + actions: { + cancel: 'Annuler', + remove: 'Supprimer', + }, + actionRequired: { + title: 'Action requise', + description: + 'La suppression du logiciel malveillant supprimera également définitivement le dossier de votre espace de stockage afin de protéger votre appareil. Cette action est irréversible.', + confirmToContinue: 'Veuillez confirmer pour continuer.', + }, + securityWarning: { + title: 'Avertissement de sécurité', + description: 'Le logiciel malveillant est toujours présent et votre appareil est menacé.', + confirmToCancel: 'Êtes-vous sûr de vouloir annuler?', + }, + }, + }, + scanProcess: { + countingFiles: 'Comptage des fichiers...', + scanning: 'Analyse en cours...', + scannedFiles: 'Fichiers analysés', + detectedFiles: 'Fichiers détectés', + errorWhileScanning: "Une erreur s'est produite lors de l'analyse des éléments. Veuillez réessayer.", + noFilesFound: { + title: 'Aucune menace détectée', + subtitle: 'Aucune action supplémentaire requise', + }, + malwareFound: { + title: 'Malware détecté', + subtitle: 'Veuillez examiner et supprimer les menaces.', + action: 'Supprimer le malware', + }, + scanAgain: 'Analyser à nouveau', + }, + filesContainingMalwareModal: { + title: 'Fichiers contenant des malwares', + selectedItems: 'Sélectionné {{selectedFiles}} sur {{totalFiles}}', + selectAll: 'Tout sélectionner', + actions: { + cancel: 'Annuler', + remove: 'Supprimer', + }, + }, + }, + cleaner: { + selectAllCheckbox: 'Tout sélectionner', + mainView: { + cleanup: 'Nettoyer', + }, + generateReportView: { + title: 'Pas encore de scans', + description: + "Analysez votre système pour trouver les fichiers que vous pouvez supprimer en toute sécurité pour libérer de l'espace.", + generateReport: "Exécuter l'analyse", + }, + loadingView: { + title: 'Attendez un instant.', + description: 'Nous générons votre rapport...', + }, + sizeIndicatorView: { + selectCategory: 'Sélectionnez une catégorie pour', + previewContent: 'aperçu du contenu', + saveUpTo: "Économisez jusqu'à", + ofYourSpace: 'de votre espace', + }, + cleanupConfirmDialogView: { + title: 'Confirmer le nettoyage', + description: + 'Cette action supprimera définitivement les fichiers sélectionnés de votre appareil. Cette action ne peut pas être annulée. Veuillez confirmer pour continuer.', + cancelButton: 'Annuler', + confirmButton: 'Supprimer les fichiers ', + }, + cleaningView: { + cleaningProcess: { + title: 'Nettoyage...', + stopCleanButton: 'Arrêter le nettoyage', + deletedFiles: 'Fichiers supprimés', + freeSpaceGained: 'Espace libre gagné', + }, + cleaningFinished: { + title: 'Votre appareil est propre', + subtitle: "Aucune autre action n'est nécessaire", + finish: 'Terminer', + }, + }, + }, + }, + issues: { + title: "Liste d'erreurs", + tabs: { + sync: 'Synchronisation', + backups: 'Sauvegardes', + general: 'Général', + antivirus: 'Antivirus', + }, + 'no-issues': 'Aucune erreur trouvée', + actions: { + 'select-folder': 'Sélectionner un dossier', + 'find-folder': 'Trouver un dossier', + 'try-again': 'Essayer à nouveau', + }, + 'report-modal': { + actions: { + close: 'Fermer', + cancel: 'Annuler', + report: 'Rapport', + send: 'Envoyer', + }, + 'help-url': "Pour obtenir de l'aide, visitez", + report: 'Vous pouvez également envoyer un rapport sur cette erreur', + 'user-comments': 'Commentaires', + 'include-logs': 'Inclure les logs de ce processus de synchronisation à des fins de diagnostic', + }, + errors: { + ABORTED: 'Avorté', + CREATE_FOLDER_FAILED: 'Erreur lors de la création de la dossier', + DELETE_ERROR: "Impossible de supprimer l'élément", + FILE_MODIFIED: 'Fichier modifié lors du téléchargement', + FILE_SIZE_TOO_BIG: 'Le fichier est trop grand (max 20GB)', + FOLDER_ACCESS_DENIED: "L'app n'a pas le droit d'accéder à cette dossier", + FOLDER_DOES_NOT_EXIST: 'Dossier non existant', + INVALID_WINDOWS_NAME: String.raw`Windows ne permet pas les noms contenant les caractères \ / : * ? " < > |`, + NETWORK_CONNECTIVITY_ERROR: 'Erreur de connectivité réseau', + NOT_ENOUGH_SPACE: "Vous n'avez pas assez d'espace pour compléter l'opération", + PARENT_FOLDER_DOES_NOT_EXIST: 'Dossier parent non existant', + ROOT_FOLDER_DOES_NOT_EXIST: 'Dossier racine non existant', + SERVER_INTERNAL_ERROR: 'Erreur de serveur interne', + UNKNOWN_DEVICE_NAME: "Impossible d'obtenir le nom de votre appareil", + WEBSOCKET_CONNECTION_ERROR: 'Erreur de connexion WebSocket', + }, + }, + common: { + cancel: 'Annuler', + }, +}; diff --git a/src/frontend/frontend.types.ts b/src/frontend/frontend.types.ts index 7bef379..004b66d 100644 --- a/src/frontend/frontend.types.ts +++ b/src/frontend/frontend.types.ts @@ -1,4 +1,6 @@ +import { Language, TranslationFn } from './core/i18n/i18n.types'; + export type LocalContextProps = { - translate: (key: string, keysToReplace?: Record) => string; - language: string; + translate: TranslationFn; + language: Language; };