From 5acae82107a3bd9bb44abae5a6d204c3d2d748a4 Mon Sep 17 00:00:00 2001 From: Andrii Nikitin Date: Tue, 28 Apr 2026 01:13:35 +0200 Subject: [PATCH 01/92] feat: add shared i18n infrastructure --- ...-transform-user_right-descriptions-i18n.js | 39 ++ ...ransform-workflow-step-config-i18n-keys.js | 81 ++++ ...0-transform-user_role-descriptions-i18n.js | 30 ++ backend/utils/TranslatableError.js | 86 ++++ backend/utils/i18n.js | 85 ++++ frontend/src/basic/LanguageSwitcher.vue | 136 ++++++ utils/modules/i18n/de/annotator.json | 20 + utils/modules/i18n/de/assessment.json | 21 + utils/modules/i18n/de/auth.json | 56 +++ utils/modules/i18n/de/basic.json | 68 +++ utils/modules/i18n/de/common.json | 118 ++++++ utils/modules/i18n/de/components.json | 32 ++ utils/modules/i18n/de/coordinator.json | 10 + utils/modules/i18n/de/dashboard.json | 392 ++++++++++++++++++ utils/modules/i18n/de/documents.json | 70 ++++ utils/modules/i18n/de/editor.json | 27 ++ utils/modules/i18n/de/errors.json | 279 +++++++++++++ utils/modules/i18n/de/index.js | 53 +++ utils/modules/i18n/de/infoPanel.json | 6 + utils/modules/i18n/de/modals.json | 44 ++ utils/modules/i18n/de/moodle.json | 14 + utils/modules/i18n/de/navigation.json | 16 + utils/modules/i18n/de/nlp.json | 125 ++++++ utils/modules/i18n/de/report.json | 10 + utils/modules/i18n/de/review.json | 9 + utils/modules/i18n/de/settings.json | 19 + utils/modules/i18n/de/sidebar.json | 41 ++ utils/modules/i18n/de/studies.json | 240 +++++++++++ utils/modules/i18n/de/submission.json | 56 +++ utils/modules/i18n/de/tagSelector.json | 6 + utils/modules/i18n/de/tags.json | 74 ++++ utils/modules/i18n/de/users.json | 82 ++++ utils/modules/i18n/en/annotator.json | 20 + utils/modules/i18n/en/assessment.json | 21 + utils/modules/i18n/en/auth.json | 56 +++ utils/modules/i18n/en/basic.json | 68 +++ utils/modules/i18n/en/common.json | 119 ++++++ utils/modules/i18n/en/components.json | 32 ++ utils/modules/i18n/en/coordinator.json | 10 + utils/modules/i18n/en/dashboard.json | 392 ++++++++++++++++++ utils/modules/i18n/en/documents.json | 69 +++ utils/modules/i18n/en/editor.json | 27 ++ utils/modules/i18n/en/errors.json | 279 +++++++++++++ utils/modules/i18n/en/index.js | 53 +++ utils/modules/i18n/en/infoPanel.json | 6 + utils/modules/i18n/en/modals.json | 44 ++ utils/modules/i18n/en/moodle.json | 14 + utils/modules/i18n/en/navigation.json | 16 + utils/modules/i18n/en/nlp.json | 126 ++++++ utils/modules/i18n/en/report.json | 10 + utils/modules/i18n/en/review.json | 9 + utils/modules/i18n/en/settings.json | 19 + utils/modules/i18n/en/sidebar.json | 41 ++ utils/modules/i18n/en/studies.json | 241 +++++++++++ utils/modules/i18n/en/submission.json | 56 +++ utils/modules/i18n/en/tagSelector.json | 6 + utils/modules/i18n/en/tags.json | 74 ++++ utils/modules/i18n/en/users.json | 83 ++++ utils/modules/i18n/index.js | 72 ++++ utils/modules/i18n/messages.js | 7 + utils/modules/i18n/package.json | 7 + 61 files changed, 4322 insertions(+) create mode 100644 backend/db/migrations/20260302143000-transform-user_right-descriptions-i18n.js create mode 100644 backend/db/migrations/20260303110000-transform-workflow-step-config-i18n-keys.js create mode 100644 backend/db/migrations/20260303112000-transform-user_role-descriptions-i18n.js create mode 100644 backend/utils/TranslatableError.js create mode 100644 backend/utils/i18n.js create mode 100644 frontend/src/basic/LanguageSwitcher.vue create mode 100644 utils/modules/i18n/de/annotator.json create mode 100644 utils/modules/i18n/de/assessment.json create mode 100644 utils/modules/i18n/de/auth.json create mode 100644 utils/modules/i18n/de/basic.json create mode 100644 utils/modules/i18n/de/common.json create mode 100644 utils/modules/i18n/de/components.json create mode 100644 utils/modules/i18n/de/coordinator.json create mode 100644 utils/modules/i18n/de/dashboard.json create mode 100644 utils/modules/i18n/de/documents.json create mode 100644 utils/modules/i18n/de/editor.json create mode 100644 utils/modules/i18n/de/errors.json create mode 100644 utils/modules/i18n/de/index.js create mode 100644 utils/modules/i18n/de/infoPanel.json create mode 100644 utils/modules/i18n/de/modals.json create mode 100644 utils/modules/i18n/de/moodle.json create mode 100644 utils/modules/i18n/de/navigation.json create mode 100644 utils/modules/i18n/de/nlp.json create mode 100644 utils/modules/i18n/de/report.json create mode 100644 utils/modules/i18n/de/review.json create mode 100644 utils/modules/i18n/de/settings.json create mode 100644 utils/modules/i18n/de/sidebar.json create mode 100644 utils/modules/i18n/de/studies.json create mode 100644 utils/modules/i18n/de/submission.json create mode 100644 utils/modules/i18n/de/tagSelector.json create mode 100644 utils/modules/i18n/de/tags.json create mode 100644 utils/modules/i18n/de/users.json create mode 100644 utils/modules/i18n/en/annotator.json create mode 100644 utils/modules/i18n/en/assessment.json create mode 100644 utils/modules/i18n/en/auth.json create mode 100644 utils/modules/i18n/en/basic.json create mode 100644 utils/modules/i18n/en/common.json create mode 100644 utils/modules/i18n/en/components.json create mode 100644 utils/modules/i18n/en/coordinator.json create mode 100644 utils/modules/i18n/en/dashboard.json create mode 100644 utils/modules/i18n/en/documents.json create mode 100644 utils/modules/i18n/en/editor.json create mode 100644 utils/modules/i18n/en/errors.json create mode 100644 utils/modules/i18n/en/index.js create mode 100644 utils/modules/i18n/en/infoPanel.json create mode 100644 utils/modules/i18n/en/modals.json create mode 100644 utils/modules/i18n/en/moodle.json create mode 100644 utils/modules/i18n/en/navigation.json create mode 100644 utils/modules/i18n/en/nlp.json create mode 100644 utils/modules/i18n/en/report.json create mode 100644 utils/modules/i18n/en/review.json create mode 100644 utils/modules/i18n/en/settings.json create mode 100644 utils/modules/i18n/en/sidebar.json create mode 100644 utils/modules/i18n/en/studies.json create mode 100644 utils/modules/i18n/en/submission.json create mode 100644 utils/modules/i18n/en/tagSelector.json create mode 100644 utils/modules/i18n/en/tags.json create mode 100644 utils/modules/i18n/en/users.json create mode 100644 utils/modules/i18n/index.js create mode 100644 utils/modules/i18n/messages.js create mode 100644 utils/modules/i18n/package.json diff --git a/backend/db/migrations/20260302143000-transform-user_right-descriptions-i18n.js b/backend/db/migrations/20260302143000-transform-user_right-descriptions-i18n.js new file mode 100644 index 000000000..119866f8d --- /dev/null +++ b/backend/db/migrations/20260302143000-transform-user_right-descriptions-i18n.js @@ -0,0 +1,39 @@ +'use strict'; + +const DESCRIPTION_BY_NAME = { + "backend.socket.user.getUsers.student": "users.rightDescriptions.backend_socket_user_getUsers_student", + "backend.socket.user.getUsers.mentor": "users.rightDescriptions.backend_socket_user_getUsers_mentor", + "frontend.dashboard.users.view": "users.rightDescriptions.frontend_dashboard_users_view", + "backend.socket.user.getUsers.all": "users.rightDescriptions.backend_socket_user_getUsers_all", + "frontend.dashboard.studies.addBulkAssignments": "users.rightDescriptions.frontend_dashboard_studies_addBulkAssignments", + "frontend.dashboard.studies.addSingleAssignments": "users.rightDescriptions.frontend_dashboard_studies_addSingleAssignments", + "frontend.dashboard.studies.fullAccess": "users.rightDescriptions.frontend_dashboard_studies_fullAccess", + "frontend.dashboard.studies.view.readOnly": "users.rightDescriptions.frontend_dashboard_studies_view_readOnly", + "frontend.dashboard.studies.view.userPrivateInfo": "users.rightDescriptions.frontend_dashboard_studies_view_userPrivateInfo", + "frontend.dashboard.home.view": "users.rightDescriptions.frontend_dashboard_home_view", + "frontend.dashboard.documents.view": "users.rightDescriptions.frontend_dashboard_documents_view", + "frontend.dashboard.tags.view": "users.rightDescriptions.frontend_dashboard_tags_view", + "frontend.dashboard.projects.view": "users.rightDescriptions.frontend_dashboard_projects_view", + "frontend.dashboard.studies.view": "users.rightDescriptions.frontend_dashboard_studies_view", + "frontend.dashboard.study_sessions.view": "users.rightDescriptions.frontend_dashboard_study_sessions_view", + "study.template.delete": "users.rightDescriptions.study_template_delete", +}; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + for (const [name, description] of Object.entries(DESCRIPTION_BY_NAME)) { + await queryInterface.bulkUpdate( + "user_right", + { description, updatedAt: new Date() }, + { name }, + {} + ); + } + }, + + async down(queryInterface, Sequelize) { + // Intentionally left as no-op because original free-text values were not uniquely preserved. + }, +}; + diff --git a/backend/db/migrations/20260303110000-transform-workflow-step-config-i18n-keys.js b/backend/db/migrations/20260303110000-transform-workflow-step-config-i18n-keys.js new file mode 100644 index 000000000..9af1f1349 --- /dev/null +++ b/backend/db/migrations/20260303110000-transform-workflow-step-config-i18n-keys.js @@ -0,0 +1,81 @@ +'use strict'; + +const REPLACEMENTS = { + "The link is added to the end of the document \n `~SESSION_HASH~` will be replace with the current session hash": + "studies.workflowConfig.addLinkEod.reviewLink.help", + "Do you find the feedback helpful?": + "studies.workflowConfig.addLinkEod.reviewText.help", + "Assessment Configuration File:": + "studies.workflowConfig.assessment.configurationId.label", + "Select the configuration file for this workflow step assessment.": + "studies.workflowConfig.assessment.configurationId.help", + "Forced Assessment": + "studies.workflowConfig.assessment.forcedAssessment.label", + "If enabled, reviewers must save a score and justification for every criterion before they can proceed.": + "studies.workflowConfig.assessment.forcedAssessment.help", + "Configuration File:": + "studies.workflowConfig.assessmentWithAi.configurationId.label", + "Select the configuration file for this workflow step.": + "studies.workflowConfig.assessmentWithAi.configurationId.help", + "Modal Size": + "studies.workflowConfig.modalSize.label", + Small: + "studies.workflowConfig.modalSize.options.small", + Medium: + "studies.workflowConfig.modalSize.options.medium", + Large: + "studies.workflowConfig.modalSize.options.large", + "Extra Large": + "studies.workflowConfig.modalSize.options.extraLarge", +}; + +function deepReplace(value) { + if (Array.isArray(value)) { + return value.map(deepReplace); + } + if (value && typeof value === "object") { + return Object.fromEntries( + Object.entries(value).map(([k, v]) => [k, deepReplace(v)]) + ); + } + if (typeof value === "string" && value in REPLACEMENTS) { + return REPLACEMENTS[value]; + } + return value; +} + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + const rows = await queryInterface.sequelize.query( + "SELECT id, configuration FROM workflow_step", + { type: Sequelize.QueryTypes.SELECT } + ); + + for (const row of rows) { + let cfg = row.configuration; + if (typeof cfg === "string") { + try { + cfg = JSON.parse(cfg); + } catch (e) { + continue; + } + } + if (!cfg || typeof cfg !== "object") { + continue; + } + const nextCfg = deepReplace(cfg); + await queryInterface.bulkUpdate( + "workflow_step", + { configuration: JSON.stringify(nextCfg), updatedAt: new Date() }, + { id: row.id }, + {} + ); + } + }, + + async down(queryInterface, Sequelize) { + // No-op: reverse mapping is intentionally omitted. + }, +}; + diff --git a/backend/db/migrations/20260303112000-transform-user_role-descriptions-i18n.js b/backend/db/migrations/20260303112000-transform-user_role-descriptions-i18n.js new file mode 100644 index 000000000..ef7799a5c --- /dev/null +++ b/backend/db/migrations/20260303112000-transform-user_role-descriptions-i18n.js @@ -0,0 +1,30 @@ +'use strict'; + +const DESCRIPTION_BY_ROLE = { + admin: "users.roleDescriptions.admin", + user: "users.roleDescriptions.user", + teacher: "users.roleDescriptions.teacher", + mentor: "users.roleDescriptions.mentor", + student: "users.roleDescriptions.student", + guest: "users.roleDescriptions.guest", + system: "users.roleDescriptions.system", +}; + +/** @type {import('sequelize-cli').Migration} */ +module.exports = { + async up(queryInterface, Sequelize) { + for (const [name, description] of Object.entries(DESCRIPTION_BY_ROLE)) { + await queryInterface.bulkUpdate( + "user_role", + { description, updatedAt: new Date() }, + { name }, + {} + ); + } + }, + + async down(queryInterface, Sequelize) { + // No-op: reverse mapping intentionally omitted. + }, +}; + diff --git a/backend/utils/TranslatableError.js b/backend/utils/TranslatableError.js new file mode 100644 index 000000000..aef10c203 --- /dev/null +++ b/backend/utils/TranslatableError.js @@ -0,0 +1,86 @@ +/** + * TranslatableError - Custom error class for i18n support + * + * This error class allows throwing errors with translation keys instead of + * hardcoded strings. The error can then be: + * - Translated to English for logging (using the i18n utility) + * - Sent to the frontend as a key for client-side translation + * + * @example + * // Simple error with just a key + * throw new TranslatableError('errors.auth.invalidCredentials'); + * + * @example + * // Error with interpolation parameters + * throw new TranslatableError('errors.nlp.timeout', { skill: 'summarization' }); + * + * @example + * // Error with parameters for dynamic messages + * throw new TranslatableError('errors.assignment.unableToAssignEnoughDocuments', { + * roleName: 'Reviewer', + * count: 5 + * }); + * + */ + +const i18n = require('./i18n'); + +class TranslatableError extends Error { + /** + * Creates a new TranslatableError + * + * @param {string} key - The translation key (e.g., 'errors.auth.invalidCredentials') + * @param {Object} params - Optional parameters for interpolation + */ + constructor(key, params = {}) { + // Call parent constructor with the key as message + // This ensures stack traces show the key + super(key); + + // Maintain proper stack trace for where the error was thrown (V8 engines) + if (Error.captureStackTrace) { + Error.captureStackTrace(this, TranslatableError); + } + + this.name = 'TranslatableError'; + this.key = key; + this.params = params; + + // Flag to identify translatable errors in catch blocks + this.isTranslatable = true; + } + + /** + * Gets the English translation of this error for logging purposes + * + * @returns {string} - The translated error message in English + */ + getLocalizedMessage() { + return i18n.t(this.key, this.params); + } + + /** + * Serializes the error for sending to the frontend + * The frontend can use this to translate the error to the user's locale + * + * @returns {Object} - Object with key and params for frontend translation + */ + toJSON() { + return { + key: this.key, + params: this.params + }; + } + + /** + * Returns the English translation when converting to string + * Useful for logging and debugging + * + * @returns {string} - The translated error message + */ + toString() { + return `${this.name}: ${this.getLocalizedMessage()}`; + } +} + +module.exports = TranslatableError; diff --git a/backend/utils/i18n.js b/backend/utils/i18n.js new file mode 100644 index 000000000..47bc299c7 --- /dev/null +++ b/backend/utils/i18n.js @@ -0,0 +1,85 @@ +/** + * Backend i18n Utility + * + * Loads English translations from the shared i18n module directory + * and provides a translation function for backend logging/fallbacks. + */ + +const fs = require('fs'); +const path = require('path'); + +let translations = null; + +function flattenObject(obj, prefix = '') { + const result = {}; + for (const key of Object.keys(obj)) { + const value = obj[key]; + const newKey = prefix ? `${prefix}.${key}` : key; + if (value && typeof value === 'object' && !Array.isArray(value)) { + Object.assign(result, flattenObject(value, newKey)); + } else { + result[newKey] = value; + } + } + return result; +} + +function loadTranslations() { + if (translations !== null) { + return translations; + } + + const i18nDir = path.resolve(__dirname, '../../utils/modules/i18n/en'); + const merged = {}; + + try { + if (!fs.existsSync(i18nDir)) { + translations = {}; + return translations; + } + + const files = fs.readdirSync(i18nDir); + for (const file of files) { + if (file.endsWith('.json')) { + const filePath = path.join(i18nDir, file); + const namespace = file.replace('.json', ''); + const content = fs.readFileSync(filePath, 'utf-8'); + merged[namespace] = JSON.parse(content); + } + } + + translations = flattenObject(merged); + } catch (_error) { + translations = {}; + } + + return translations; +} + +function interpolate(text, params = {}) { + if (!text || typeof text !== 'string') { + return text; + } + + return text.replace(/\{(\w+)\}/g, (match, key) => { + if (Object.prototype.hasOwnProperty.call(params, key)) { + return String(params[key]); + } + return match; + }); +} + +function t(key, params = {}) { + const trans = loadTranslations(); + if (Object.prototype.hasOwnProperty.call(trans, key)) { + return interpolate(trans[key], params); + } + return key; +} + +function hasKey(key) { + const trans = loadTranslations(); + return Object.prototype.hasOwnProperty.call(trans, key); +} + +module.exports = { t, hasKey, loadTranslations }; diff --git a/frontend/src/basic/LanguageSwitcher.vue b/frontend/src/basic/LanguageSwitcher.vue new file mode 100644 index 000000000..a6a1884b9 --- /dev/null +++ b/frontend/src/basic/LanguageSwitcher.vue @@ -0,0 +1,136 @@ + + + + + \ No newline at end of file diff --git a/utils/modules/i18n/de/annotator.json b/utils/modules/i18n/de/annotator.json new file mode 100644 index 000000000..a822795c9 --- /dev/null +++ b/utils/modules/i18n/de/annotator.json @@ -0,0 +1,20 @@ +{ + "documentNote": "Dokumentnotiz", + "createdByUser": "Erstellt von Benutzer {userId}", + "messages": { + "unsavedAnnotations": "Nicht gespeicherte Anmerkungen", + "unsavedAnnotationsWarning": "Sind Sie sicher, dass Sie den Annotator verlassen möchten? Ungespeicherte Änderungen gehen verloren." + }, + "annotations": "Anmerkungen", + "submitReview": "ÜberprĂŒfung einreichen", + "report": "Bericht", + "accept": "Akzeptieren", + "reject": "Ablehnen", + "hideStudyComments": "Studienkommentare ausblenden", + "showStudyComments": "Studienkommentare anzeigen", + "deactivateNlpSupport": "NLP-UnterstĂŒtzung deaktivieren", + "activateNlpSupport": "NLP-UnterstĂŒtzung aktivieren", + "downloadAnnotations": "Anmerkungen herunterladen", + "documentSubscribeError": "Dokumentabonnement-Fehler", + "replies": "Antworten" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/assessment.json b/utils/modules/i18n/de/assessment.json new file mode 100644 index 000000000..b6c843de7 --- /dev/null +++ b/utils/modules/i18n/de/assessment.json @@ -0,0 +1,21 @@ +{ + "title": "Bewertung", + "noConfiguration": "Keine Bewertungskonfiguration verfĂŒgbar.", + "totalPoints": "{points} Pkt.", + "criteria": { + "unnamedCriterion": "Unbenanntes Kriterium", + "justification": "BegrĂŒndung:", + "noJustification": "Keine BegrĂŒndung angegeben", + "editPlaceholder": "BegrĂŒndung bearbeiten...", + "edit": "Bearbeiten", + "changeScore": "Punktzahl Ă€ndern", + "saved": "Bewertung gespeichert", + "save": "Bewertung speichern", + "saveEdit": "Speichern", + "cancel": "Abbrechen" + }, + "rubric": { + "unnamedRubric": "Unbenanntes Bewertungsschema", + "noCriteria": "Keine Kriterien fĂŒr dieses Bewertungsschema definiert." + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/auth.json b/utils/modules/i18n/de/auth.json new file mode 100644 index 000000000..d684b56f3 --- /dev/null +++ b/utils/modules/i18n/de/auth.json @@ -0,0 +1,56 @@ +{ + "login": "Anmelden", + "logout": "Abmelden", + "register": "Registrieren", + "username": "Benutzername", + "password": "Passwort", + "email": "E-Mail", + "emailAddress": "E-Mail-Adresse", + "firstName": "Vorname", + "lastName": "Nachname", + "forgotPassword": "Passwort vergessen?", + "resetPassword": "Passwort zurĂŒcksetzen", + "changePassword": "Passwort Ă€ndern", + "currentPassword": "Aktuelles Passwort", + "newPassword": "Neues Passwort", + "confirmPassword": "Passwort bestĂ€tigen", + "loginAsGuest": "Als Gast anmelden", + "usernameOrEmail": "Benutzername oder E-Mail", + "signedInAs": "Angemeldet als {username}", + "updateConsent": "Zustimmung aktualisieren", + "termsOfService": "Nutzungsbedingungen", + "acceptTerms": "Ich akzeptiere die Nutzungsbedingungen", + "acceptStats": "Ich erlaube die Erfassung anonymer Statistiken", + "acceptDataSharing": "Ich stimme zu, dass meine Daten fĂŒr Forschungszwecke verfĂŒgbar gemacht werden", + "acceptStatsBehavior": "Ich erlaube die Erfassung von Verhaltensstatistiken fĂŒr Forschungszwecke", + "acceptAndContinue": "Akzeptieren & Fortfahren", + "emailVerificationRequired": "E-Mail-Verifizierung erforderlich", + "resendVerificationEmail": "Verifizierungs-E-Mail erneut senden", + "returnToLogin": "ZurĂŒck zur Anmeldung", + "backToLogin": "ZurĂŒck zur Anmeldung", + "placeholders": { + "newPasswordPlaceholder": "Neues Passwort eingeben (mindestens 8 Zeichen)", + "confirmPasswordPlaceholder": "Neues Passwort bestĂ€tigen" + }, + "messages": { + "emailVerified": "E-Mail verifiziert", + "emailVerifiedSuccess": "Ihre E-Mail-Adresse wurde erfolgreich verifiziert. Sie können sich jetzt anmelden.", + "resetTokenValid": "Token ist gĂŒltig.", + "validationLinkSent": "Ein Validierungslink wurde an Ihre E-Mail-Adresse gesendet", + "validateEmail": "Verifizieren Sie Ihre E-Mail-Adresse", + "registrationSuccess": "Registrierung erfolgreich! Sie können sich jetzt anmelden.", + "logoutSuccess": "Sitzung beendet.", + "passwordResetLinkSent": "Ein Link zum ZurĂŒcksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.", + "passwordResetInstructions": "Wir senden Anweisungen zum ZurĂŒcksetzen des Passworts an diese E-Mail-Adresse.", + "emailNotVerified": "Ihre E-Mail-Adresse wurde noch nicht verifiziert. Bitte ĂŒberprĂŒfen Sie Ihren Posteingang auf eine Verifizierungs-E-Mail.", + "resendVerificationPrompt": "E-Mail nicht erhalten? Klicken Sie auf die SchaltflĂ€che unten, um sie erneut zu senden.", + "verificationEmailSent": "Verifizierungs-E-Mail wurde erfolgreich gesendet.", + "validatingResetToken": "Passwort-ZurĂŒcksetzen-Token wird ĂŒberprĂŒft...", + "passwordResetSuccess": "Das Passwort wurde erfolgreich zurĂŒckgesetzt. Sie können sich jetzt mit Ihrem neuen Passwort anmelden.", + "termsUpdated": "Nutzungsbedingungen erfolgreich aktualisiert", + "termsUpdatedMessage": "Die Nutzungsbedingungen wurden erfolgreich aktualisiert", + "consentUpdated": "Zustimmung erfolgreich aktualisiert", + "consentUpdatedMessage": "Die Zustimmungseinstellungen wurden erfolgreich aktualisiert" + }, + "copyright": "Urheberrecht © 2022-2024 Team Care UKP Lab (TU Darmstadt)" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/basic.json b/utils/modules/i18n/de/basic.json new file mode 100644 index 000000000..aff9fa70b --- /dev/null +++ b/utils/modules/i18n/de/basic.json @@ -0,0 +1,68 @@ +{ + "form": { + "placeholders": { + "documentBracket": "" + } + }, + "configuration": { + "title": "Konfiguration", + "filesTitle": "Konfigurationsdateien", + "uploadButton": "Konfiguration hochladen", + "uploadTooltip": "Neue Konfigurationsdatei hochladen", + "types": { + "assessment": "Bewertung", + "validation": "Validierung" + }, + "viewer": { + "title": "Konfiguration: {name}" + }, + "editor": { + "title": "Konfiguration bearbeiten: {name}", + "placeholder": "JSON-Inhalt hier bearbeiten..." + }, + "delete": { + "title": "Konfiguration löschen", + "message": "Möchten Sie \"{name}\" wirklich löschen?" + }, + "tooltips": { + "view": "Konfiguration anzeigen", + "edit": "Konfiguration bearbeiten", + "delete": "Konfiguration löschen" + }, + "steps": { + "general": "Allgemeine Einstellungen", + "services": "Dienste", + "placeholders": "Platzhalter" + }, + "editButton": "Konfiguration bearbeiten", + "saveButton": "Konfiguration speichern", + "toasts": { + "updatedTitle": "Konfiguration aktualisiert", + "updatedMessage": "Die Konfigurationsdaten wurden erfolgreich aktualisiert.", + "loadErrorTitle": "Konfigurationsfehler", + "loadErrorMessage": "Fehler beim Laden des Konfigurationsinhalts: {error}", + "editorNotInit": "Editor nicht initialisiert", + "noContent": "Kein Konfigurationsinhalt zum Speichern", + "invalidJsonTitle": "UngĂŒltiges JSON", + "invalidJsonMessage": "Bitte ĂŒberprĂŒfen Sie Ihre JSON-Syntax: {error}", + "updateErrorTitle": "Fehler beim Aktualisieren der Konfiguration", + "updateErrorMessage": "Aktualisierung der Konfiguration fehlgeschlagen", + "deleteFailedTitle": "Löschen der Konfiguration fehlgeschlagen" + }, + "stepTitles": { + "general": "Allgemeine Konfiguration", + "services": "Dienste-Konfiguration", + "placeholders": "Platzhalter-Konfiguration" + } + }, + "consent": { + "successTitle": "Zustimmung erfolgreich aktualisiert", + "successMessage": "Die Zustimmungseinstellungen wurden erfolgreich aktualisiert.", + "errorTitle": "Fehler beim Aktualisieren der Zustimmung" + + }, + "export": { + "successTitle": "Export erfolgreich", + "successMessage": "{id} erfolgreich exportiert" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/common.json b/utils/modules/i18n/de/common.json new file mode 100644 index 000000000..2a7040d23 --- /dev/null +++ b/utils/modules/i18n/de/common.json @@ -0,0 +1,118 @@ +{ + "yes": "Ja", + "no": "Nein", + "ok": "OK", + "save": "Speichern", + "cancel": "Abbrechen", + "close": "Schließen", + "abort": "Abbrechen", + "decline": "Ablehnen", + "confirm": "BestĂ€tigen", + "back": "ZurĂŒck", + "previous": "Vorherige", + "next": "Weiter", + "nextText": "Weiter", + "new": "Neu", + "add": "HinzufĂŒgen", + "create": "Erstellen", + "edit": "Bearbeiten", + "editItem": "{item} bearbeiten", + "change": "Ändern", + "update": "Aktualisieren", + "delete": "Löschen", + "copy": "Kopieren", + "download": "Herunterladen", + "upload": "Hochladen", + "import": "Importieren", + "export": "Exportieren", + "reload": "Neu laden", + "loading": "Wird geladen...", + "noData": "Keine Daten", + "success": "Erfolg", + "error": "Fehler", + "warning": "Warnung", + "info": "Info", + "readOnly": "SchreibgeschĂŒtzt", + "id": "ID", + "name": "Name", + "title": "Titel", + "createdAt": "Erstellt am", + "updatedAt": "Zuletzt geĂ€ndert", + "type": "Typ", + "status": "Status", + "public": "Öffentlich", + "actions": "Aktionen", + "manage": "Verwalten", + "search": "Suchen", + "filter": "Filtern", + "sortBy": "Sortieren nach", + "page": "Seite", + "of": "von", + "show": "Anzeigen", + "start": "Start", + "end": "Ende", + "created": "Erstellt", + "user": "Benutzer", + "userName": "Benutzername", + "userId": "Benutzer-ID", + "email": "E-Mail", + "extId": "extId", + "firstName": "Vorname", + "lastName": "Nachname", + "groupId": "Gruppen-ID", + "dataExisting": "Daten vorhanden", + "loadingFromServer": "Lade Daten vom Server...", + "typeToFilter": "Tippen zum Filtern...", + "submitText": "Absenden", + "required": "Dieses Feld ist erforderlich", + "select": "AuswĂ€hlen", + "baseFileType": "Basis-Datentyp wĂ€hlen:", + "example": "Beispiel", + "input": "Eingabe", + "output": "Ausgabe", + "config": "Konfiguration", + "send": "Senden", + "note": "Hinweis:", + "stepper": { + "stepNotImplemented": "Schritt {step} ist nicht implementiert." + }, + "itemsPerPage": "EintrĂ€ge pro Seite", + "all": "Alle", + "label": "Paginierung", + "assign": "Zuweisen", + "confirmation": "BestĂ€tigung", + "project": "Projekt", + "language": "Sprache", + "reset": "ZurĂŒcksetzen", + "na": "k.A.", + "time": { + "seconds": "{sec}s", + "minutesSeconds": "{min}m {sec}s", + "hoursMinutesSeconds": "{h}h {min}m {sec}s", + "minutes": "min" + }, + "reply": "Antworten", + "hide": "Verbergen", + "showMore": "Mehr anzeigen", + "showLess": "Weniger anzeigen", + "hideMore": "Mehr verbergen", + "summarize": "Zusammenfassen", + "apply": "Anwenden", + "unknown": "Unbekannt", + "submission": "Einreichungen", + "assignments": "Zuweisungen", + "use": "Verwenden", + "hideReplies": "Antworten verbergen", + "connecting": "Verbinden...", + "loadingProgress": "Lade {appLoadStep} ({percent}%)", + "duplicate": "Duplizieren", + "notSet": "Nicht gesetzt", + "details": "Details", + "view": "Ansehen", + "updated": "Aktualisiert", + "refresh": "Aktualisieren", + "configure": "Konfigurieren", + "anonymous": "Anonym", + "unlimited": "unbegrenzte" + +} \ No newline at end of file diff --git a/utils/modules/i18n/de/components.json b/utils/modules/i18n/de/components.json new file mode 100644 index 000000000..a9eb98a24 --- /dev/null +++ b/utils/modules/i18n/de/components.json @@ -0,0 +1,32 @@ +{ + "logs":{ + "title": "Protokolle", + "columns": { + "level": "Stufe", + "time": "Zeit", + "service": "Dienst", + "message": "Nachricht" + }, + "levels": { + "error": "Fehler", + "warn": "Warnung", + "info": "Info", + "debug": "Debug" + } + }, + "comment":{ + "enterText": "Text eingeben...", + "noComment": "Kein Kommentar", + "sentimentAnalysis": "Sentiment-Analyse", + "saveCommand": "Speichern (Strg + Enter)" + }, + "voteButtons":{ + "helpful": "Hilfreich", + "notHelpful": "Nicht hilfreich" + }, + "pdftoolbar":{ + "minToolbar": "Symbolleiste minimieren", + "showToolbar": "Symbolleiste anzeigen" + } + +} \ No newline at end of file diff --git a/utils/modules/i18n/de/coordinator.json b/utils/modules/i18n/de/coordinator.json new file mode 100644 index 000000000..d37cc7264 --- /dev/null +++ b/utils/modules/i18n/de/coordinator.json @@ -0,0 +1,10 @@ +{ + "entryUpdated": "Der Eintrag wurde erfolgreich aktualisiert!", + "entryAdded": "Der Eintrag wurde erfolgreich hinzugefĂŒgt!", + "errors": { + "noFieldsDefined": "Die Tabelle {table} hat keine definierten Felder!", + "saveFailed": "Konnte nicht gespeichert werden", + "incompleteConfig": "UnvollstĂ€ndige Konfiguration", + "incompleteConfigDetail": "Sie haben eine unvollstĂ€ndige Konfiguration bei {steps}" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/dashboard.json b/utils/modules/i18n/de/dashboard.json new file mode 100644 index 000000000..72f6d2fd4 --- /dev/null +++ b/utils/modules/i18n/de/dashboard.json @@ -0,0 +1,392 @@ +{ + "projects": { + "title": "Projekte", + "assignProjectsToUsers": "Projekte Benutzern zuweisen", + "selectProjectToAssign": "Projekt zum Zuweisen auswĂ€hlen:", + "OneProjectSelected": "1 Projekt ausgewĂ€hlt", + "ZeroProjectsSelected": "0 Projekte ausgewĂ€hlt", + "selectUsersToAssignProjectsTo": "Benutzer auswĂ€hlen, denen Projekte zugewiesen werden sollen:", + "usersSelected": "Benutzer ausgewĂ€hlt", + "confirmAssignment": "Zuweisung bestĂ€tigen:", + "summary": "Zusammenfassung:", + "aboutToAssign": "Sie sind dabei, {projectCount} Projekt(e) {userCount} Benutzer(n) zuzuweisen.", + "noteLabel": "Hinweis:", + "noteBody": "Durch die Zuweisung von Benutzern zu diesem Projekt wird das Projekt automatisch öffentlich gemacht.", + "selectedProjects": "AusgewĂ€hlte Projekte:", + "selectedUsers": "AusgewĂ€hlte Benutzer:", + "selectProjects": "Projekte auswĂ€hlen", + "selectUsers": "Benutzer auswĂ€hlen", + "selectProject": "Projekt auswĂ€hlen", + "assignmentFailed": "Zuweisung fehlgeschlagen", + "selectMessage": "Bitte wĂ€hlen Sie ein Projekt und mindestens einen Benutzer aus.", + "projectAssignmentFailed": "Projektzuweisung fehlgeschlagen", + "projectAssigned": "Projekt zugewiesen", + "successfullyAssignedMessage": "Das Projekt wurde erfolgreich {count} Benutzer(n) zugewiesen.", + "exportData": "Daten exportieren", + "exportStudySessions": "Exportiere eine Liste aller Studiensitzungen mit Hash:", + "totalStudies": "Studien gesamt:", + "totalStudySessions": "Studiensitzungen gesamt:", + "exportingAllData": "Exportiere alle Daten", + "totalTags": "Tags gesamt:", + "totalTagSets": "Tag-Sets gesamt:", + "totalProjects": "Projekte gesamt:", + "totalDocuments": "Dokumente gesamt:", + "totalAnnotations": "Anmerkungen gesamt:", + "totalComments": "Kommentare gesamt:", + "totalCommentsVotes": "Kommentar-Abstimmungen gesamt:", + "totalEdits": "Bearbeitungen gesamt:", + "exportType": "Exporttyp", + "exportReviewers": "Liste aller Reviewer exportieren", + "extId": "extId", + "numberOfAssignments": "Anzahl der Zuweisungen", + "roles": "Rollen", + "filterTable": "Woraus soll gefiltert werden?", + "createTooltip": "Projekt erstellen", + "assignButton": "Projekte zuweisen", + "assignTooltip": "Projekte zuweisen", + "coordinator": { + "title": "Projekt" + }, + "columns": { + "name": "Projektname", + "public": "Öffentlich", + "closed": "Geschlossen" + }, + "actions": { + "copy": "Projekt kopieren", + "edit": "Projekt bearbeiten", + "delete": "Projekt löschen", + "share": "Projekt teilen", + "export": "Daten exportieren", + "selectDefault": "Projekt als Standard auswĂ€hlen" + }, + "delete": { + "title": "Projekt löschen", + "message": "Möchten Sie dieses Projekt wirklich löschen?", + "warningStudies": "Derzeit ist {count} Studie mit diesem Projekt verknĂŒpft. Wenn Sie das Projekt löschen, wird auch die Studie gelöscht. | Derzeit sind {count} Studien mit diesem Projekt verknĂŒpft. Wenn Sie das Projekt löschen, werden auch die Studien gelöscht.", + "warningDocuments": "Derzeit ist {count} Dokument mit diesem Projekt verknĂŒpft. Wenn Sie das Projekt löschen, wird auch das Dokument gelöscht. | Derzeit sind {count} Dokumente mit diesem Projekt verknĂŒpft. Wenn Sie das Projekt löschen, werden auch die Dokumente gelöscht." + }, + "toasts": { + "deleteFailed": "Projekt konnte nicht gelöscht werden", + "publishFailed": "Projekt konnte nicht veröffentlicht werden", + "publishedTitle": "Projekt veröffentlicht", + "publishedMessage": "Das Projekt wurde erfolgreich veröffentlicht." + }, + "fields": { + "name": { + "label": "Name des Projekts", + "placeholder": "Mein Projekt" + }, + "description": { + "label": "Beschreibung des Projekts", + "placeholder": "Meine Projektbeschreibung" + }, + "publicSwitch": "Ist das Projekt öffentlich?" + } + }, + "settings": { + "selectSetting": "Einstellung auswĂ€hlen", + "selectedValue": "AusgewĂ€hlter Wert:", + "usersSelected": "Benutzer ausgewĂ€hlt", + "setting:": "Einstellung:", + "newValue": "Neuer Wert:", + "users:": "Benutzer:", + "noteBody1": "Dies aktualisiert die ausgewĂ€hlte benutzerspezifische Einstellung fĂŒr alle ausgewĂ€hlten Benutzer. Die globale Standardeinstellung wird nicht geĂ€ndert.", + "setting": "Einstellung", + "selectedUsers": "AusgewĂ€hlte Benutzer", + "updateFailed": "Aktualisierung fehlgeschlagen", + "selectSettingAndUser": "Bitte wĂ€hlen Sie eine Einstellung und mindestens einen Benutzer aus.", + "settingsUpdated": "Einstellungen aktualisiert", + "updatedMessage": "\"{key}\" fĂŒr {count} Benutzer aktualisiert.", + "mainSettings": "Haupteinstellungen der Anwendung", + "sensitiveDataNote": "Hinweis: Stellen Sie sicher, dass keine sensiblen Daten enthalten sind!", + "toolbarNote": "Hinweis: Wenn die Toolbar deaktiviert ist, werden alle Tools ausgeblendet!", + "nlpSupport": "NLP-UnterstĂŒtzung aktivieren/deaktivieren" + }, + "study": { + "addSingleAssignment": "Einzelne Zuweisung hinzufĂŒgen", + "addReviewer": "Reviewer hinzufĂŒgen", + "addReviewers": "Reviewer hinzufĂŒgen", + "reviewersAdded": "Reviewer hinzugefĂŒgt", + "reviewersAddedMessage": "Die Reviewer wurden erfolgreich hinzugefĂŒgt", + "failedToAddReviewers": "Reviewer konnten nicht hinzugefĂŒgt werden", + "createBulkAssignment": "Sammelzuweisung erstellen", + "noStudyTemplatesAvailable": "Es sind keine Studienvorlagen verfĂŒgbar!", + "createTemplateToProceed": "Bitte erstellen Sie eine Studienvorlage, um fortzufahren!", + "workflowSteps": "Workflow-Schritte:", + "workflowStepWithIndex": "Workflow-Schritt {index}:", + "assignmentBase": "Zuweisung soll basieren auf:", + "annotator": "Annotator", + "editor": "Editor", + "filterUsersWithDocuments": "Nur Benutzer mit Dokumenten filtern", + "filterUsersFromPreviousDocuments": "Nur Benutzer aus zuvor ausgewĂ€hlten Dokumenten filtern", + "defineTheNumberOfReviews": "Definieren Sie die Anzahl der Reviews, die jeder Benutzer der Rolle durchfĂŒhren soll:", + "noRolesAvailable": "Es sind keine Rollen verfĂŒgbar!", + "selectReviewersOrChangeMode": "Bitte wĂ€hlen Sie Reviewer mit Rollen aus oder Ă€ndern Sie den Auswahlmodus!", + "discontributeDocuments": "Dokumente zwischen den ausgewĂ€hlten Reviewern verteilen:", + "remainingAssignments": "Verbleibende Zuweisungen:", + "selectMode": "Bitte wĂ€hlen Sie einen Reviewer-Auswahlmodus", + "createAssignmentConfirmPrompt": "Möchten Sie die Zuweisung wirklich mit den folgenden Details erstellen?", + "warning": "Warnung:", + "notReviewOwnDocument": "Der Zuweisungsprozess stellt sicher, dass ein Reviewer nicht sein eigenes Dokument reviewed.", + "warning1": "Dies kann zu einem Fehlschlag im Zuweisungsprozess fĂŒhren,", + "warning2": "stellen Sie daher sicher, dass die Werte korrekt gesetzt sind, damit die Zuweisung erfolgreich ist.", + "template": "Vorlage:", + "workflow": "Workflow:", + "documents": "Dokumente:", + "reviewers": "Reviewer:", + "reviewsToCreate": "Zu erstellende Reviews:", + "selectionMode": "Auswahlmodus:", + "roles": "Rollen:", + "submissionWithId": "Einreichung {id}", + "templateSelection": "Vorlagenauswahl", + "documentSelection": "Dokumentauswahl", + "reviewerSelection": "Reviewer-Auswahl", + "distribution": "Verteilung", + "reviewerSelectionMode": "Reviewer-Auswahlmodus", + "roleBasedSelection": "Rollenbasierte Auswahl (Anzahl der Dokumente, die von jedem Benutzer der ausgewĂ€hlten Rollen reviewed werden sollen)", + "reviewerBasedSelection": "Reviewer-basierte Auswahl (Dokumente zwischen den ausgewĂ€hlten Reviewern verteilen)", + "nameOfReviewsForRole": "Anzahl der Reviews fĂŒr Rolle: ", + "nameofReviewsForUsers": "Anzahl der Reviews fĂŒr Benutzer: ", + "reviews": "Review(s)", + "assignmentCreated": "Zuweisung erstellt", + "assignmentCreatedMessage": "Die Zuweisung wurde erfolgreich erstellt", + "failedToCreateAssignment": "Zuweisung konnte nicht erstellt werden", + "bulkCloseStudies": "Studien gesammelt schließen", + "closeStudiesPrompt": "Möchten Sie wirklich alle offenen Studien schließen?", + "allStudiesClosed": "Alle Studien geschlossen", + "closeAllStudies": "Alle Studien schließen", + "allStudiesClosedMessage": "Alle offenen Studien wurden geschlossen", + "failedToClose": "Schließen aller Studien fehlgeschlagen", + "createTemplate": "Vorlage erstellen", + "deleteTemplate": "Vorlage löschen", + "deleteTemplatePrompt": "Möchten Sie diese Vorlage wirklich löschen?", + "studyTemplateDeleted": "Studienvorlage gelöscht", + "studyTemplateDeletedMessage": "Die Studienvorlage wurde gelöscht", + "deletionFailed": "Löschen der Studienvorlage fehlgeschlagen", + "assignmentType": "Zuweisungstyp:", + "workflowAssignments": "Workflow-Zuweisungen:", + "createAssignment": "Zuweisung erstellen", + "assignmentSelection": "Zuweisungsauswahl", + "studySessionsOf": "Studiensitzungen von", + "openSession": "Sitzung öffnen", + "inspectSession": "Sitzung prĂŒfen", + "copySessionLink": "Sitzungslink kopieren", + "deleteSession": "Sitzung löschen", + "notYet": "noch nicht", + "deleteSessionNote": "Sie sind dabei, eine Sitzung zu löschen; wenn Sie die Sitzung nur beenden möchten, öffnen Sie bitte die Sitzung und brechen Sie das Löschen ab.", + "studySessionDeleted": "Studiensitzung gelöscht", + "studySessionHasBeenDeleted": "Die Studiensitzung wurde gelöscht", + "studySessionNotDeleted": "Studiensitzung nicht gelöscht", + "studySessionCopiedMessage": "Studiensitzungslink in die Zwischenablage kopiert!" + }, + "users": { + "manageRightsFor": "Berechtigungen verwalten fĂŒr", + "role": "Rolle", + "selectRightsNote": "WĂ€hlen Sie die Berechtigungen fĂŒr diese Rolle aus. Hinweis: Alle Benutzer haben standardmĂ€ĂŸig grundlegende {user}-Berechtigungen.", + "userWithQuotes": "\"user\"", + "selectRole": "Rolle auswĂ€hlen", + "manageRights": "Berechtigungen verwalten", + "rightName": "Berechtigungsname", + "description": "Beschreibung", + "chooseARole": "WĂ€hlen Sie eine Rolle, die dem Benutzer zugewiesen werden soll.", + "roleRightsUpdated": "Rollenberechtigungen aktualisiert", + "roleRightsUpdatedMessage": "Die Rollenberechtigungen wurden erfolgreich aktualisiert", + "userNameLabel": "Benutzername:", + "firstNameLabel": "Vorname:", + "lastNameLabel": "Nachname:", + "emailLabel": "E-Mail:", + "updatedAt": "Aktualisiert am", + "deletedAt": "Gelöscht am", + "userUpdated": "Benutzer aktualisiert", + "userUpdatedMessage": "Benutzer erfolgreich aktualisiert!", + "bulkImportUsers": "Benutzer gesammelt importieren", + "dragAndDropCSV": "CSV-Datei hierher ziehen und ablegen", + "orClickToUpload": "oder klicken, um hochzuladen", + "csvTemplateHint": "Bitte prĂŒfen Sie das Format oder {0} hier.", + "downloadTemplate": "Vorlage herunterladen", + "bulkImportConfirm": "Möchten Sie wirklich {newCount} Benutzer gesammelt erstellen {br} und {dupCount} Benutzer ĂŒberschreiben?", + "resultSummary": "{newCount} Benutzer erfolgreich erstellt und {updatedCount} Benutzer ĂŒberschrieben", + "failedListTitle": "Die folgenden Benutzer konnten nicht erstellt werden:", + "userCannotBeAdded": "Benutzer mit externer ID {extId} kann nicht hinzugefĂŒgt werden: {message}", + "uploadToMoodle": "In Moodle hochladen", + "downloadResultCsv": "Ergebnis-CSV herunterladen", + "moodle": "Moodle", + "preview": "Vorschau", + "result": "Ergebnis", + "uploadingCompleted": "Upload abgeschlossen", + "uploadingCompletedMessage": "Bitte gehen Sie zu Moodle, um Ihren Benutzernamen und Ihr Passwort zu ĂŒberprĂŒfen!", + "validationCompleted": "Validierung abgeschlossen", + "validationCompletedMessage": "CSV ist gĂŒltig!", + "pleaseUploadCsv": "Bitte laden Sie eine CSV-Datei hoch", + "viewUserRight": "Benutzerberechtigung anzeigen", + "userHasNoAssignedRights": "Dieser Benutzer hat keine zugewiesenen Berechtigungen", + "userRole": "Benutzerrolle", + "userRight": "Benutzerberechtigung", + "okay": "OK", + "adminHasFullRights": "Administrator hat alle Rechte", + "roleNoAssociatedRights": "Diese Rolle hat noch keine zugeordneten Berechtigungen", + "csvErrorHint": "Ihre CSV-Datei enthĂ€lt die folgenden Fehler. Bitte beheben Sie diese und laden Sie die Datei erneut hoch.", + "placeholders": { + "provideFirstName": "Bitte geben Sie den Vornamen an", + "provideLastName": "Bitte geben Sie den Nachnamen an", + "provideUsername": "Bitte geben Sie den Benutzernamen an – keine Sonderzeichen", + "passwordMinLength": "Das Passwort sollte mindestens 8 Zeichen lang sein", + "emailExample": "email@example.com" + }, + "passwordLabel": "Passwort:", + "userCreationCompleted": "Benutzererstellung abgeschlossen", + "userCreationCompletedMessage": "Die Benutzererstellung war erfolgreich" + }, + "submission": { + "assignGroup": { + "title": "Gruppe zuweisen", + "applyPercentage": "Prozentsatz der aktuellen Auswahl anwenden (zufĂ€llig gewĂ€hlt):", + "applyButton": "Anwenden", + "targetCount": "{percentage}% → {target} von {total}", + "stepOne": "Einreichungen auswĂ€hlen", + "stepTwo": "Gruppeneinstellungen", + "stepThree": "PrĂŒfen & bestĂ€tigen", + "groupNumber": "Gruppennummer", + "groupNumberPlaceholder": "Gruppennummer eingeben", + "additionalSettings": "ZusĂ€tzliche Einstellungen", + "additionalSettingsPlaceholder": "Geben Sie zusĂ€tzliche Einstellungen ein", + "copySubmissions": "Einreichungen kopieren", + "createCopyiesOfSubmissionsLabel": "Kopien der ausgewĂ€hlten Einreichungen mit der angegebenen Gruppennummer erstellen.", + "summaryTitle": "Zuweisungszusammenfassung", + "numberOfSubmissions": "Anzahl der Einreichungen:", + "groupNumberLabel": "Gruppennummer:", + "additionalSettingsLabel": "ZusĂ€tzliche Einstellungen:", + "copySubmissionsLabel": "Einreichungen kopieren:", + "reviewNote": "Bitte prĂŒfen Sie die obenstehenden Informationen, bevor Sie absenden.", + "successTitle": "Gruppe zugewiesen", + "successMessage": "{count} Einreichung(en) erfolgreich der Gruppe {group} zugewiesen", + "failureTitle": "Gruppe konnte nicht zugewiesen werden", + "columns": { + "additionalSettings": "ZusĂ€tzliche Einstellungen" + }, + "filters": { + "noGroupId": "Keine GroupID" + } + } + }, + "importModal": { + "title": "Moodle-Einreichungen importieren", + "stepMoodle": "Moodle", + "stepPreview": "Vorschau", + "stepConfigure": "Konfigurieren", + "stepConfirm": "BestĂ€tigen", + "stepResult": "Ergebnis", + "assignGroup": "Gruppe zuweisen", + "groupNumber": "Gruppennummer", + "groupNumberPlaceholder": "Gruppennummer eingeben", + "confirmImport": "Importeinstellungen bestĂ€tigen", + "importSummary": "Import-Zusammenfassung", + "submissionsToImport": "Zu importierende Einreichungen:", + "groupNumberLabel": "Gruppennummer:", + "validationSchema": "Validierungsschema:", + "noneSelected": "Nichts ausgewĂ€hlt", + "totalSubmissions": "Einreichungen gesamt:", + "requiredFiles": "Erforderliche Dateien:", + "validationDetails": "Validierungsdetails:", + "validationWillCheck": "Dies validiert den Inhalt der ZIP-Datei gemĂ€ĂŸ dem Schema \"{name}\". Einreichungen mĂŒssen alle erforderlichen Dateien enthalten: {files}.", + "noValidationSelected": "Kein Validierungsschema ausgewĂ€hlt. Einreichungen werden ohne Validierung importiert.", + "areYouSure": "Möchten Sie wirklich {count} {message} importieren?", + "submissionSingular": "Einreichung", + "submissionPlural": "Einreichungen", + "successfullyImported": "{count} Einreichung(en) erfolgreich importiert", + "failedToImport": "Die folgenden Einreichungen konnten nicht importiert werden:", + "userCannotBeImported": "Benutzer mit der Benutzer-ID {userId} kann nicht importiert werden: {message}", + "downloadErrorCSV": "Fehler-CSV herunterladen", + "failedGetSubmissions": "Studentische Einreichungen konnten nicht aus Moodle abgerufen werden", + "failedImportSubmissions": "Einreichung konnte nicht aus Moodle importiert werden", + "columns": { + "duplicate": "Duplikat", + "externalId": "Externe ID", + "userId": "Benutzer-ID", + "firstName": "Vorname", + "lastName": "Nachname", + "fileCount": "Dateianzahl" + }, + "filters": { + "new": "Neu", + "duplicate": "Duplikat" + } + }, + "publishModal": { + "titleReviews": "Reviews veröffentlichen", + "titleSubmissions": "Einreichungen veröffentlichen", + "stepDocumentSelection": "Dokumentauswahl", + "stepSubmissionSelection": "Einreichungsauswahl", + "stepSessionSelection": "Sitzungsauswahl", + "stepConfirmation": "BestĂ€tigung", + "stepPublishingOptions": "Veröffentlichungsoptionen", + "textFormat": "Textformat:", + "placeholderSessionLinks": "Der Platzhalter ~SESSION_LINKS~ wird durch die Review-Links ersetzt.", + "placeholderUsername": "Der Platzhalter ~USERNAME~ wird durch den CARE-Benutzernamen des Dokumentbesitzers ersetzt.", + "linkCollection": "Link-Sammlung:", + "basedOnStudies": "basierend auf Studien (Sitzungslinks fĂŒr jede Studie)", + "basedOnSessions": "basierend auf Sitzungen (Links zu eigenen Sitzungen)", + "links": "Links:", + "publishMethod": "Veröffentlichungsmethode:", + "downloadCSV": "CSV herunterladen", + "chooseDownloadCSV": "WĂ€hlen Sie \"CSV herunterladen\", um den generierten Feedback-Text fĂŒr jeden EmpfĂ€nger zu exportieren.", + "publishReviewLinks": "Studiensitzungslinks veröffentlichen", + "csvSuccessfullyGenerated": "CSV erfolgreich erstellt und exportiert", + "reviewsPublished": "Reviews veröffentlicht", + "reviewLinksPublished": "Die Review-Links wurden erfolgreich veröffentlicht!", + "failedPublishReviews": "Reviews konnten nicht veröffentlicht werden", + "columns": { + "extId": "extId", + "submissionId": "Einreichungs-ID", + "group": "Gruppe", + "firstName": "Vorname", + "lastName": "Nachname", + "studies": "Studien", + "sessions": "Sitzungen", + "documentTitle": "Dokumenttitel", + "studyName": "Studienname" + } + }, + "uploadModal": { + "title": "Einreichung hochladen", + "stepSelectUser": "Benutzer auswĂ€hlen", + "stepSelectConfig": "Konfiguration auswĂ€hlen", + "stepUploadFile": "Datei hochladen", + "assignGroup": "Gruppe zuweisen", + "groupNumber": "Gruppennummer", + "groupNumberPlaceholder": "Gruppennummer eingeben", + "invalidFiles": "UngĂŒltige Datei(en)", + "pleaseUploadFiles": "Bitte laden Sie alle erforderlichen Dateien hoch.", + "uploadedFile": "Hochgeladene Datei", + "fileSuccessfullyUploaded": "Datei erfolgreich hochgeladen!", + "failedUploadFile": "Datei konnte nicht hochgeladen werden", + "columns": { + "id": "ID", + "extId": "extId", + "firstName": "Vorname", + "lastName": "Nachname", + "userName": "Benutzername" + } + }, + "systemRoles": { + "regular": "Standardnutzer", + "maintainer": "Verwalter", + "admin": "Administrator", + "system": "System", + + "descriptions": { + "regular": "Keine Systemrechte", + "maintainer": "Benutzerverwaltung", + "admin": "Volle Kontrolle", + "system": "Systembenutzer" + } + }, + "documents": { + "fields": { + "selectDoc": "Dokument auswĂ€hlen", + "newEmptyDoc": "Neues leeres Dokument" + } + } +} + diff --git a/utils/modules/i18n/de/documents.json b/utils/modules/i18n/de/documents.json new file mode 100644 index 000000000..7180a29b2 --- /dev/null +++ b/utils/modules/i18n/de/documents.json @@ -0,0 +1,70 @@ +{ + "title": "Dokumente", + "document": "Dokument", + "documentDefaultName": "dokument", + "addDocument": "Dokument hinzufĂŒgen", + "uploadDocument": "Dokument hochladen", + "uploadNewDocument": "Neues Dokument hochladen", + "uploadConfiguration": "Neue Konfigurationsdatei hochladen", + "createDocument": "Dokument erstellen", + "createNewDocument": "Neues Dokument erstellen", + "renameDocument": "Dokument umbenennen...", + "deleteDocument": "Dokument löschen...", + "accessDocument": "Dokument öffnen...", + "publishDocument": "Dokument veröffentlichen...", + "downloadPdfWithAnnotations": "PDF mit Annotationen herunterladen", + "exportDelta": "Delta in eine lokale Datei exportieren", + "exportHtml": "HTML in eine lokale Datei exportieren", + "openStudyCoordinator": "Study Coordinator öffnen...", + "importAnnotations": "Annotationen importieren", + "typeOfDocument": "Dokumenttyp", + "chooseDocumentType": "Dokumenttyp auswĂ€hlen...", + "nameOfDocument": "Name des Dokuments", + "yesPublish": "Ja, veröffentlichen!", + "types": { + "pdf": "PDF", + "html": "HTML", + "modal": "MODAL", + "generalHtml": "Allgemeines HTML-Dokument", + "studyModal": "Study-Modal-Dokument (nur in Studien verwendbar)" + }, + "messages": { + "deleteConfirm": "Sind Sie sicher, dass Sie das Dokument löschen möchten?", + "deleteTitle": "Dokument löschen", + "studyWarning": "Derzeit laufen {count} Studien zu diesem Dokument. Wenn Sie es löschen, werden die Studien ebenfalls gelöscht!", + "documentPublished": "Dokument erfolgreich veröffentlicht!", + "documentAvailableAt": "Das Dokument ist unter folgendem Link verfĂŒgbar:", + "publishConfirm": "Möchten Sie das Dokument wirklich veröffentlichen?", + "cannotBeUndone": "Dies kann nicht rĂŒckgĂ€ngig gemacht werden!", + "documentPublishedTitle": "Dokument veröffentlicht", + "publishedSuccess": "Dokument erfolgreich veröffentlicht!", + "linkCopiedMessage": "Link in die Zwischenablage kopiert!", + "documentEdited": "Das Dokument wurde erfolgreich bearbeitet.", + "documentEditedTitle": "Dokument bearbeitet", + "documentEditedMessage": "Dokument erfolgreich bearbeitet!", + "configurationUploaded": "Konfiguration hochgeladen", + "fileUploaded": "Datei wurde erfolgreich hochgeladen.", + "annotationsAdded": "{count} Annotationen wurden hinzugefĂŒgt.", + "annotationImportPartialFailure": "Das Dokument wurde hochgeladen, aber die automatische Annotationsextraktion ist fehlgeschlagen. Sie können das Dokument weiterhin verwenden, jedoch fehlen möglicherweise einige Annotationen.", + "issuesOccurred": "Es sind einige Probleme aufgetreten", + "uploadedWithWarnings": "Mit Warnungen hochgeladen", + "uploadedFile": "Hochgeladene Datei", + "documentCreated": "Dokument erfolgreich erstellt.", + "documentNotFoundTitle": "Dokument nicht gefunden", + "documentErrorTitle": "Dokumentfehler" + }, + "downloadPdf": { + "title": "PDF herunterladen", + "includeAnnotations": "Annotationen im PDF einschließen", + "preparing": "PDF wird vorbereitet...", + "toasts": { + "successTitle": "PDF erfolgreich heruntergeladen", + "successMessage": "Ihr PDF wurde heruntergeladen.", + "successMessageWithAnnotations": "Ihr PDF mit Annotationen wurde heruntergeladen.", + "failedTitle": "PDF-Download fehlgeschlagen", + "unknownError": "Unbekannter Fehler" + } + } +} + + diff --git a/utils/modules/i18n/de/editor.json b/utils/modules/i18n/de/editor.json new file mode 100644 index 000000000..717f1bcc4 --- /dev/null +++ b/utils/modules/i18n/de/editor.json @@ -0,0 +1,27 @@ +{ + "reqTitle": "Anfrage senden", + "cmdTitle": "Befehl senden", + "cmdToSend": "der zu sendende Befehl", + "serviceToContact": "der zu kontaktierende Dienst", + "waitingForResponse": "Antwort wird erwartet", + "payload": "Dateninhalt", + "emptyMsgHistory": "Keine Nachrichten gesendet/empfangen.", + "messages": { + "msgNotReceived": "Innerhalb von 5 Sekunden keine Nachricht vom Server empfangen." + }, + "seePayload": "Dateninhalt ansehen", + "request": "Anfrage", + "copyJsonSuccess": { + "title": "JSON kopiert", + "message": "JSON in die Zwischenablage kopiert!" + }, + "editJson": "JSON bearbeiten", + "unsavedWarning": { + "unsavedChanges": "Ungespeicherte Änderungen", + "unsavedChangesMessage": "Möchten Sie die Seite wirklich verlassen? Es gibt ungespeicherte Änderungen, die verloren gehen." + }, + "history": "Verlauf", + "configurator": "Konfigurator", + "readOnly": "SchreibgeschĂŒtzt", + "downloadDocument": "Dokument herunterladen" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/errors.json b/utils/modules/i18n/de/errors.json new file mode 100644 index 000000000..1f9be7ad0 --- /dev/null +++ b/utils/modules/i18n/de/errors.json @@ -0,0 +1,279 @@ +{ + "auth": { + "invalidResetLink": "UngĂŒltiger Link zum ZurĂŒcksetzen des Passworts. Bitte fordern Sie ein neues Passwort an.", + "invalidResetToken": "UngĂŒltiges Reset-Token. Bitte fordern Sie ein neues Passwort an.", + "invalidOrExpiredToken": "UngĂŒltiges oder abgelaufenes Reset-Token.", + "tokenRequired": "Token ist erforderlich.", + "tokenAndPasswordRequired": "Token und neues Passwort sind erforderlich.", + "failedToValidateToken": "Validierung des Reset-Tokens fehlgeschlagen. Bitte versuchen Sie es erneut.", + "failedToResetPassword": "ZurĂŒcksetzen des Passworts fehlgeschlagen. Bitte versuchen Sie es spĂ€ter erneut.", + "passwordResetFailed": "ZurĂŒcksetzen des Passworts fehlgeschlagen", + "passwordResetDisabled": "Das ZurĂŒcksetzen des Passworts ist deaktiviert.", + "passwordResetRateLimited": "Bitte warten Sie {minutes} Minute(n), bevor Sie eine weitere E-Mail zum ZurĂŒcksetzen des Passworts anfordern.", + "emailVerificationError": "Fehler bei der BestĂ€tigung der E-Mail", + "emailVerificationDisabled": "E-Mail-Verifizierung ist deaktiviert.", + "emailAlreadyVerified": "Die E-Mail-Adresse ist bereits verifiziert.", + "verificationRateLimited": "Bitte warten Sie {minutes} Minute(n), bevor Sie eine weitere Verifizierungs-E-Mail anfordern.", + "failedToVerifyEmail": "E-Mail konnte nicht bestĂ€tigt werden. Bitte versuchen Sie es spĂ€ter erneut.", + "failedToSendResetEmail": "Die E-Mail zum ZurĂŒcksetzen des Passworts konnte nicht gesendet werden.", + "failedToSendVerificationEmail": "BestĂ€tigungs-E-Mail konnte nicht gesendet werden. Bitte versuchen Sie es spĂ€ter erneut.", + "failedToLogin": "Anmeldung fehlgeschlagen.", + "failedToCreateUser": "Benutzer konnte nicht erstellt werden.", + "emailAlreadyTaken": "E-Mail-Adresse ist bereits vergeben.", + "usernameTaken": "Benutzername ist bereits vergeben.", + "userNotFoundByEmail": "Benutzer mit dieser E-Mail-Adresse existiert nicht.", + "invalidCredentials": "UngĂŒltige Anmeldedaten", + "termsUpdateError": "Fehler beim Aktualisieren der Zustimmung", + "consentUpdateError": "Aktualisierung der Zustimmung fehlgeschlagen" + }, + "permission": { + "accessError": "Zugriffsfehler", + "accessDenied": "Zugriff verweigert.", + "noPermission": "Sie haben keine Berechtigung, diese Aktion auszufĂŒhren.", + "noUploadAccess": "Sie haben keine Berechtigung, Dokumente hochzuladen.", + "noUserAccess": "Sie haben keine Berechtigung, auf die Daten dieses Benutzers zuzugreifen.", + "noRoleAccess": "Sie haben nicht die erforderliche Rolle, um diese Aktion auszufĂŒhren.", + "noAnnotationChangePermission": "Sie haben keine Berechtigung, diese Annotation zu verĂ€ndern.", + "cannotUpdateOtherUserTable": "Sie sind nicht berechtigt, die Tabelle {dataTable} fĂŒr einen anderen Benutzer zu aktualisieren.", + "noDataAccess": "Sie haben keine Berechtigung, auf diese Daten zuzugreifen", + "noCommentEditPermission": "Sie sind nicht berechtigt, diesen Kommentar zu bearbeiten.", + "noCommentPermission": "Sie sind nicht berechtigt, einen Kommentar hinzuzufĂŒgen.", + "noCommentAccess": "Sie haben keinen Zugriff auf diesen Kommentar", + "noPermissionToAccesData": "Sie haben keine Berechtigung, auf diese Daten zuzugreifen", + "noPreprocessSubmissionPermission": "Sie haben keine Berechtigung, Einreichungen vorzuverarbeiten" + }, + "configuration": { + "idRequired": "Konfigurations-ID ist erforderlich.", + "contentRequired": "Konfigurationsinhalt ist erforderlich.", + "notFound": "Konfiguration nicht gefunden." + }, + "validation": { + "fillAllFields": "Bitte fĂŒllen Sie alle Felder korrekt aus.", + "ensurePasswordRequirements": "Bitte stellen Sie sicher, dass die Passwörter den Anforderungen entsprechen.", + "validationError": "Validierungsfehler", + "validationFailed": "Validierung fehlgeschlagen: {message}", + "required": "Dieses Feld ist erforderlich", + "requiredFieldMissing": "Erforderliches Feld fehlt: {fieldKey}", + "fileDownloadFailed": "Datei {fileName} konnte nicht heruntergeladen werden: {message}", + "schemaNotFound": "Validierungsschema nicht gefunden: {configurationId}", + "additionalFilesNotAllowed": "ZusĂ€tzliche Dateien sind nicht erlaubt. Gefunden: {files}", + "requiredFileMissing": "Erforderliche Datei fehlt: {file}", + "cannotOpenZip": "ZIP-Datei {fileName} kann nicht geöffnet werden: {message}", + "requiredFileMissingInZip": "Erforderliche Datei fehlt in ZIP {zipFileName}: {file}", + "tooManyMatchesInZip": "Zu viele Treffer fĂŒr {file} in ZIP {zipFileName}: gefunden {found}, maximal {max}", + "zipReadError": "Fehler beim Lesen der ZIP-Datei {fileName}: {message}", + "auth": { + "provideUsername": "Bitte geben Sie einen gĂŒltigen Benutzernamen an.", + "providePassword": "Bitte geben Sie ein gĂŒltiges Passwort mit mindestens 8 Zeichen an.", + "provideEmail": "Bitte geben Sie eine gĂŒltige E-Mail-Adresse an.", + "provideFirstName": "Bitte geben Sie Ihren Vornamen an.", + "provideLastName": "Bitte geben Sie Ihren Nachnamen an.", + "usernameNoSpecialChars": "Bitte geben Sie einen gĂŒltigen Benutzernamen ohne Sonderzeichen an.", + "passwordMinLength": "Ihr Passwort muss mindestens 8 Zeichen lang sein.", + "acceptTermsRequired": "Bitte akzeptieren Sie die Nutzungsbedingungen.", + "passwordsDoNotMatch": "Die Passwörter stimmen nicht ĂŒberein." + }, + "documents": { + "selectValidType": "Bitte wĂ€hlen Sie einen gĂŒltigen Dokumententyp aus.", + "noName": "Kein Name angegeben", + "enterName": "Bitte geben Sie einen Namen fĂŒr das Dokument ein." + } + }, + "file": { + "noFileUploaded": "Keine Datei hochgeladen", + "invalidFileType": "UngĂŒltiger Dateityp", + "onlyJsonAllowed": "Nur JSON-Dateien sind erlaubt.", + "onlyPdfDeltaAllowed": "Nur PDF- und Delta-Dateien sind erlaubt.", + "invalidJson": "UngĂŒltiges JSON-Format", + "jsonMustBeObject": "Das JSON muss ein Objekt mit SchlĂŒssel/Wert-Paaren sein.", + "noFileSelected": "Keine Datei ausgewĂ€hlt", + "selectJsonFile": "Bitte wĂ€hlen Sie eine JSON-Datei zum Importieren aus.", + "noTableAvailable": "{tableType} steht nicht zur Auswahl.", + "noParameters": "Keine Parameter fĂŒr die Dateiauswahl gefunden. Alle Parameter verwenden konfigurationsbasierte Eingaben.", + "pdfNotFound": "PDF-Datei wurde nicht gefunden", + "tableNameRequired": "Tabellenname ist erforderlich", + "copyJsonError": { + "title": "JSON nicht kopiert", + "notCopiedMsg": "JSON konnte nicht in die Zwischenablage kopiert werden!", + "notLoadedMsg": "JSON konnte nicht kopiert werden, da es nicht geladen oder leer ist." + }, + "pdfLoadingError": { + "title": "Fehler beim Laden der PDF-Datei", + "message": "Laden der PDF-Datei fehlgeschlagen. Stellen Sie sicher, dass die Datei nicht beschĂ€digt ist und im gĂŒltigen PDF-Format vorliegt." + } + }, + "clipboard": { + "linkNotCopied": "Link nicht kopiert", + "copyFailed": "Link konnte nicht in die Zwischenablage kopiert werden!", + "retrieveFailed": "Die URL konnte nicht abgerufen werden. Bitte versuchen Sie es spĂ€ter erneut.", + "configNotCopied": "Konfiguration nicht kopiert", + "skillConfigCopyFailed": "Skill-Konfiguration konnte nicht in die Zwischenablage kopiert werden!", + "couldNotCopyStudySession":"Link zur Studiensitzung konnte nicht in die Zwischenablage kopiert werden!" + }, + "documents": { + "deleteFailed": "Löschen des Dokuments fehlgeschlagen", + "documentNotPublished": "Dokument nicht veröffentlicht", + "documentEditFailed": "Bearbeitung des Dokuments fehlgeschlagen", + "failedToUploadConfiguration": "Fehler beim Hochladen der Konfiguration", + "failedToUpload": "Hochladen fehlgeschlagen", + "failedToProcessPdf": "Verarbeitung der PDF-Datei fehlgeschlagen", + "errorProcessingPdf": "Fehler bei der Verarbeitung der PDF-Datei", + "failedToLoadDocContent": "Laden des Dokumenteninhalts fehlgeschlagen.", + "documentOpenError": "Fehler beim Öffnen des Dokuments", + "documentCloseError": "Fehler beim Schließen des Dokuments", + "documentError": "Dokumentfehler", + "uploadingFailed": "Hochladen fehlgeschlagen", + "noDocumentSelected": "Sie mĂŒssen ein Dokument auswĂ€hlen.", + "notFound": "Dokument nicht gefunden.", + "unsupportedDocumentTypeOperation": "Diese Operation wird nur fĂŒr HTML/MODAL-Dokumente unterstĂŒtzt.", + "processingError": "Fehler bei der Verarbeitung von Dokument {documentId}: {message}", + "fileNotFound": "Datei fĂŒr Dokument {documentId} nicht gefunden: {filePath}", + "readError": "Fehler beim Lesen der Dokumentdatei {documentId}: {message}", + "notEnoughDocumentsForRole": "Nicht genĂŒgend Dokumente zur ÜberprĂŒfung fĂŒr die Rolle {roleName}. Bitte fĂŒgen Sie weitere Dokumente hinzu.", + "notEnoughDocumentsForReviewer": "Nicht genĂŒgend Dokumente zur ÜberprĂŒfung fĂŒr {reviewerName}. Bitte fĂŒgen Sie weitere Dokumente hinzu." + }, + "editor": { + "cursorPositionError": { + "title": "Keine Cursorposition", + "message": "Bitte klicken Sie in den Editor, um die Cursorposition festzulegen, bevor Sie einen Platzhalter einfĂŒgen. " + }, + "previousEditFailed": "Vorherige Bearbeitung fehlgeschlagen. Bitte versuchen Sie es erneut.", + "editHistoryRetrievalFailed": "Fehler beim Abrufen des Bearbeitungsverlaufs" + }, + "studies": { + "studyCannotStart": "Studie kann nicht gestartet werden!", + "studyClosingFailed": "Schließen der Studie fehlgeschlagen", + "studyDeleteFailed": "Löschen der Studie fehlgeschlagen", + "studyRestartFailed": "Neustart der Studie fehlgeschlagen", + "templateSaveFailed": "Speichern der Vorlage fehlgeschlagen", + "templateCreationFailed": "Erstellung der Vorlage fehlgeschlagen", + "sessionNotFinished": "Sitzung nicht beendet", + "stepUpdateFailed": "Aktualisierung des Schritts fehlgeschlagen", + "studyClosed": "Diese Studie ist geschlossen", + "studyEnded": "Diese Studie ist beendet", + "studyNotFound": "Studie nicht gefunden", + "studyNotStarted": "Diese Studie wurde noch nicht gestartet", + "sessionLimitExceeded": "Es können nicht mehr als {limit} Sitzungen erstellt werden.", + "sessionLimitPerUserExceeded": "Es können nicht mehr als {limit} Sitzungen fĂŒr diesen Benutzer erstellt werden.", + "missingContextOrStepDocuments": "Kontext oder Schrittdokumente in den Optionen fehlen. Transaktion wird abgebrochen.", + "studyStep": { + "notFound": "Kein erster Schritt fĂŒr diese Studie gefunden", + "referencedStepNotFound": "Referenzierter Studienschritt fĂŒr Workflow-Schritt {originalEntryId} nicht gefunden", + "referencedDocumentNotFound": "Referenziertes Dokument fĂŒr Studienschritt {referencedStudyStepId} nicht gefunden", + "documentNotFound": "Dokument nicht gefunden: Dokument-ID {dataDocumentId} fehlt fĂŒr Schritt {dataWorkflowStepId}", + "documentTypeMismatch": "Dokumenttyp stimmt nicht ĂŒberein: Schritt {dataWorkflowStepId} erwartet ein Editor-Dokument (Typ 1), es wurde jedoch Typ {documentType} gefunden." + } + }, + "settings": { + "errorLoading": "Fehler beim Laden der Einstellungen", + "errorSaving": "Fehler beim Speichern der Einstellungen", + "failedToImport": "Import der Einstellungen fehlgeschlagen", + "noAccessPermission": "Sie haben keine Berechtigung, auf die Einstellungen zuzugreifen.", + "noSavePermission": "Sie haben keine Berechtigung, die Einstellungen zu speichern." + }, + "users": { + "errorFetchingUsers": "Fehler beim Abrufen der Nutzer", + "userNotDeleted": "Nutzer nicht gelöscht", + "updateFailed": "Aktualisierung fehlgeschlagen", + "failedToGetUsersFromMoodle": "Fehler beim Abrufen der Nutzer von Moodle", + "failedToBulkCreateUsers": "Fehler beim Massenanlegen von Nutzern", + "failedToCheckDuplicateUsers":"Fehler beim ÜberprĂŒfen doppelter Nutzer", + "failedToCheckDuplicateUsersMessage": "Bitte wenden Sie sich an das CARE-Team, um das Problem zu beheben.", + "errorFetchingUserRights": "Fehler beim Abrufen der Nutzerrechte", + "userCreationFailed": "Erstellung des Nutzers fehlgeschlagen", + "userNotFound": "Nutzer wurde nicht gefunden", + "failedToUpdateUser": "Fehler beim Aktualisieren des Nutzers: Nutzer wurde nicht gefunden", + "noUserFoundForRole": "FĂŒr die Rolle {roleName} wurden keine Benutzer gefunden. Bitte fĂŒgen Sie der Rolle Benutzer hinzu." + }, + "submission": { + "notFound": "Einreichung mit ID {submissionId} nicht gefunden", + "documentCopyFailed": "Fehler beim Kopieren des Dokuments mit ID {documentId}: {message}", + "noValidFiles": "Keine gĂŒltigen Dateien fĂŒr Einreichung {submissionId} gefunden", + "missingAdminRights": "Vorverarbeitung kann nicht abgebrochen werden: fehlende Administratorrechte", + "noActivePreprocessing": "Vorverarbeitung kann nicht abgebrochen werden: keine aktive Vorverarbeitung", + "invalidPreprocessRequest": "UngĂŒltige Anfrage zur Vorverarbeitung.", + "noSkillParameterMappings": "Keine Skill-Parameterzuordnungen angegeben.", + "copyFailed": "Die Einreichung {submissionId} konnte nicht kopiert werden. Fehler: {originalMessage}" + }, + "tags": { + "tagSetDeleteFailed": "Löschen des Tag-Sets fehlgeschlagen", + "tagSetPublishFailed": "Veröffentlichung des Tag-Sets fehlgeschlagen", + "tagSetEmpty": "Tag-Set ist leer", + "tagSetEmptyMessage": "Sie können kein leeres Tag-Set als Standard auswĂ€hlen.", + "tagUpdateFailed": "Aktualisierung des Tags fehlgeschlagen", + "emptyTagset": { + "title": "Leeres Tagset", + "message": "Es wurde kein Tag-Set oder ein leeres Tag-Set ausgewĂ€hlt. Annotationen können nicht erstellt werden." + } + + }, + "annotator": { + "commentNotUpdated": "Kommentar nicht aktualisiert", + "annotationUpdateFailed": "Aktualisierung der Annotation fehlgeschlagen", + "annotationNotRetrieved": "Annotation nicht abgerufen", + "commentsNotRetrieved": "Kommentare nicht abgerufen" + }, + "nlp": { + "timeout": "ZeitĂŒberschreitung bei der Anfrage fĂŒr Skill {skill} - Anfrage fehlgeschlagen!", + "invalidService": "Der bereitgestellte Service ist ungĂŒltig. Bitte wenden Sie sich an den Serviceanbieter.", + "configCopyFailed": "Konfiguration nicht geladen oder leer, kann nicht kopiert werden.", + "downloadFailed": "Download fehlgeschlagen", + "configDownloadFailed": "Fehler beim Herunterladen der Skill-Konfiguration, da sie nicht geladen ist", + "msgNotReceived": "Keine Nachricht vom Server innerhalb von 5 Sekunden erhalten." + }, + "server": { + "unexpectedError": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.", + "unknownError": "Unbekannter Fehler" + }, + "page": { + "notFoundTitle": "404 - Nicht gefunden", + "notFoundMessage": "Die Seite, die Sie suchen, existiert nicht." + }, + "download": { + "abortedTitle": "Download abgebrochen", + "serverTimeout": "Der Server hat nicht geantwortet. Bitte versuchen Sie es spĂ€ter erneut.", + "inProgress": "Ein weiterer Download ist im Gange. Bitte warten Sie.", + "exportAbortedTitle": "Export abgebrochen", + "exportFailedTitle": "Export fehlgeschlagen", + "exportFailedMessage": "Export fĂŒr {id} fehlgeschlagen." + }, + "element": { + "invalidInput": "Die Eingabe ist ungĂŒltig.", + "fieldRequired": "Dieses Feld ist erforderlich." + }, + "collaboration": { + "collabUpdateFailed": "Aktualisierung der Kollaboration fehlgeschlagen", + "collabCreationFailed": "Kollaboration konnte nicht gestartet werden" + }, + "connectionError": "Verbindungsfehler! Verbindung wird wiederhergestellt...", + "roles": { + "loadAvailableRightsFailed": "Fehler beim Laden der verfĂŒgbaren Rechte", + "loadRoleRightsFailed": "Rollenberechtigungen konnten nicht geladen werden", + "assignRoleRightsFailed": "Rollenberechtigungen konnten nicht zugewiesen werden" + }, + "csv": { + "missingRequiredHeaders": "CSV-Datei enthĂ€lt nicht alle erforderlichen Überschriften", + "emptyValue": "Leerer Wert gefunden fĂŒr {key} an Index {index}", + "duplicateId": "Doppelte ID gefunden: {extId} an Index {index}", + "duplicateEmail": "Doppelte E-Mail gefunden: {email} an Index {index}", + "rolesNotCommaSeparated": "Rollen sind nicht durch Kommas getrennt fĂŒr ID {id} an Index {index}", + "invalidEmailFormat": "UngĂŒltiges E-Mail-Format fĂŒr ID {id} an Index {index}: {email}", + "parseError": "Fehler beim Verarbeiten der Datei: {message}" + }, + "rpc": { + "serviceNotConnected": "Kein Verbindung zum RPC-Dienst", + "requestFailed": "RPC-Anfrage {eventName} fehlgeschlagen: {message}", + "downloadFailed": "Herunterladen von Einreichungen fehlgeschlagen: {message}", + "annotationExtractionFailed": "Extraktion von Annotationen fehlgeschlagen: {message}", + "annotationEmbeddingFailed": "Einbettung von Annotationen fehlgeschlagen: {message}", + "annotationDeletionFailed": "Loeschen von Annotationen fehlgeschlagen: {message}" + }, + "database": { + "failedToUpdateData": "Aktualisierung der Daten fehlgeschlagen" + }, + "assignment": { + "unableToAssignEnoughDocuments": "Es konnten nicht genĂŒgend Dokumente fĂŒr {reviewerName} in der Rolle {roleName} zugewiesen werden.", + "couldNotAssignReviewers": "Nicht alle Reviewer konnten zugewiesen werden. Bitte versuchen Sie es erneut.", + "invalidMode":"FĂŒr die Erstellung der Zuweisung wurde ein ungĂŒltiger Modus angegeben." + } +} diff --git a/utils/modules/i18n/de/index.js b/utils/modules/i18n/de/index.js new file mode 100644 index 000000000..5a5015313 --- /dev/null +++ b/utils/modules/i18n/de/index.js @@ -0,0 +1,53 @@ +import common from './common.json' +import auth from './auth.json' +import errors from './errors.json' +import dashboard from './dashboard.json' +import documents from './documents.json' +import users from './users.json' +import studies from './studies.json' +import annotator from './annotator.json' +import settings from './settings.json' +import tags from './tags.json' +import modals from './modals.json' +import nlp from './nlp.json' +import navigation from './navigation.json' +import assessment from './assessment.json' +import editor from './editor.json' +import tagSelector from './tagSelector.json' +import infoPanel from './infoPanel.json' +import report from './report.json' +import review from './review.json' +import basic from './basic.json' +import coordinator from './coordinator.json' +import moodle from './moodle.json' +import submission from './submission.json' +import sidebar from './sidebar.json' +import components from './components.json' + +export default { + common, + auth, + errors, + dashboard, + documents, + users, + studies, + annotator, + settings, + tags, + modals, + nlp, + navigation, + assessment, + editor, + tagSelector, + infoPanel, + report, + review, + basic, + coordinator, + moodle, + submission, + sidebar, + components, +} diff --git a/utils/modules/i18n/de/infoPanel.json b/utils/modules/i18n/de/infoPanel.json new file mode 100644 index 000000000..3eb89da9a --- /dev/null +++ b/utils/modules/i18n/de/infoPanel.json @@ -0,0 +1,6 @@ +{ + "description": "Beschreibung:", + "maxPoints": "Maximale Punktzahl:", + "pointsAbbreviation": "Pkt.", + "scoringCriteria": "Bewertungskriterien:" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/modals.json b/utils/modules/i18n/de/modals.json new file mode 100644 index 000000000..e22eb9043 --- /dev/null +++ b/utils/modules/i18n/de/modals.json @@ -0,0 +1,44 @@ +{ + "confirm": "BestĂ€tigen", + "confirmAction": "BestĂ€tige {action}", + "pleaseConfirm": "Bitte bestĂ€tigen", + "sending": "Wird gesendet...", + "sendResetEmail": "E-Mail zum ZurĂŒcksetzen des Passworts senden", + "passwordReset": "Passwort zurĂŒckgesetzt", + "passwordUpdated": "Passwort aktualisiert", + "passwordResetSuccess": "Das Passwort wurde erfolgreich zurĂŒckgesetzt.", + "loading": "Wird geladen...", + "closeModal": "Schließen", + "placeholders": { + "documentPreview": "Dokumentvorschau", + "placeholderLegend": "Platzhalter Legende", + "configurePlaceholders": "Platzhalter konfigurieren", + "firstDataSource": "Erste Datenquelle:", + "secondDataSource": "Zweite Datenquelle:", + "dataSource": "Datenquelle:", + "selectFirstDataSource": "Erste Datenquelle auswĂ€hlen...", + "selectSecondDataSource": "Zweite Datenquelle auswĂ€hlen...", + "selectDataSource": "Datenquelle auswĂ€hlen...", + "noPlaceholders": "Keine Platzhalter im Dokument gefunden.", + "documentError": "Dokumentenfehler", + "invalidDocumentContent": "Der Dokumentinhalt ist ungĂŒltig oder leer. Bitte versuchen Sie es erneut.", + "failedToFetchDocument": "Fehler beim Abrufen des Dokuments.", + "addInformation": "FĂŒgen Sie hier die Informationen fĂŒr den Platzhalter hinzu:", + "dataMissingOrInvalid": "~ Platzhalterdaten fehlen oder sind ungĂŒltig ~", + "dataMissing": "~ Platzhalterdaten fehlen ~", + "firstVersionStep": "Erste Version (Schritt {step})", + "currentVersionStep": "Aktuelle Version (Schritt {step})" + }, + "modal": "Modal", + "noContentForThisStep": "FĂŒr diesen Schritt sind keine Inhalte verfĂŒgbar.", + "finishStudy": "Studie beenden", + "exportStudyData": "Studiendaten exportieren", + "returnToStudies": "'RĂŒckkehr zu Studien'", + "revisions": { + "revision": "Überarbeitung", + "revisionOne": "Überarbeitung 1", + "revisionTwo": "Überarbeitung 2" + }, + "chart": "Diagramm", + "comparisonChart": "Vergleichsdiagramm" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/moodle.json b/utils/modules/i18n/de/moodle.json new file mode 100644 index 000000000..a64a11f3f --- /dev/null +++ b/utils/modules/i18n/de/moodle.json @@ -0,0 +1,14 @@ +{ + "assignmentId": "Aufgaben-ID:", + "courseId": "Kurs-ID:", + "apiKey": "Moodle-API-SchlĂŒssel:", + "apiUrl": "Moodle-URL:", + "refresh": "Aktualisieren", + "refreshTooltip": "Aufgabenliste aktualisieren", + "placeholders": { + "assignmentId": "Aufgaben-ID eingeben", + "courseId": "Kurs-ID eingeben", + "apiKey": "API-SchlĂŒssel eingeben", + "apiUrl": "https://example.moodle.com" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/navigation.json b/utils/modules/i18n/de/navigation.json new file mode 100644 index 000000000..1ac4fcd28 --- /dev/null +++ b/utils/modules/i18n/de/navigation.json @@ -0,0 +1,16 @@ +{ + "goBack": "ZurĂŒck...", + "project": "Projekt: {name}", + "documentation": "Dokumentation", + "feedback": "Feedback", + "projectPage": "Projektseite", + "sidebar": { + "collapseSidebar": "Seitenleiste einklappen", + "toggleSidebar": "Seitenleiste umschalten", + "hideSidebar": "Seitenleiste ausblenden", + "showSidebar": "Seitenleiste einblenden", + "moreActions": "Weitere Aktionen", + "noContent": "Kein Inhalt in der Seitenleiste ausgewĂ€hlt.", + "sidebarSection": "Seitenleistenbereich" + } +} diff --git a/utils/modules/i18n/de/nlp.json b/utils/modules/i18n/de/nlp.json new file mode 100644 index 000000000..c0714f44c --- /dev/null +++ b/utils/modules/i18n/de/nlp.json @@ -0,0 +1,125 @@ +{ + "service": "NLP-Dienst", + "serviceRequest": "NLP-Dienstanfrage", + "notAvailable": "{name} nicht verfĂŒgbar", + "skillDetails": "Skill-Details", + "copyConfig": "Konfiguration kopieren", + "downloadConfig": "Konfiguration herunterladen", + "sendCommand": "Befehl senden", + "configCopied": "Konfiguration kopiert", + "skillConfigCopied": "Skill-Konfiguration in die Zwischenablage kopiert!", + "downloadSuccess": "Download erfolgreich", + "downloadedConfigMessage": "Konfiguration {name} heruntergeladen", + "services": { + "availableServices": "VerfĂŒgbare Dienste", + "noServices": "FĂŒr diesen Schritt ist keine Dienstkonfiguration verfĂŒgbar." + }, + "inputConfirm": { + "confirmSelections": "BestĂ€tigen Sie Ihre Auswahl", + "selectedSkill": "AusgewĂ€hlter Skill:", + "inputMappings": "Input-Zuordnungen:", + "selectedFiles": "AusgewĂ€hlte Dateien:", + "baseFileSelections": "Auswahl der Basisdateien:", + "defaultConfiguration": "Konfiguration", + "unknownSelection": "Unbekannt" + }, + "inputFiles": { + "filesSelectedFor": "FĂŒr {param} ausgewĂ€hlte Dateien: {count} Datei(en)", + "selectFilesFor": "Bitte wĂ€hlen Sie Dateien fĂŒr den Parameter aus: {param}", + "documents": "Dokumente", + "submissions": "Einreichungen", + "noGroupId": "Keine GroupID" + }, + "inputGroup": { + "validationConfiguration": "Validierungskonfiguration {id}" + }, + "skillSelector": { + "selectNlpSkill": "Bitte wĂ€hlen Sie einen NLP-Skill aus:" + }, + "inputMap": { + "inputMapping": "Input-Zuordnung", + "outputMapping": "Output-Zuordnung", + "saveInDocumentData": "In Dokumentdaten speichern", + "insertIntoEditor": "In den Editor einfĂŒgen" + }, + "request": { + "title": "NLP-Dienstanfrage", + "timeout": "ZeitĂŒberschreitung bei der Anfrage fĂŒr Skill: {skill}" + }, + "preprocessing": { + "title": "Vorverarbeitung der Bewertung", + "cancelButton": "Vorverarbeitung abbrechen", + "submissionName": "Einreichung {id}", + "cancelApplySkills": "Skill-Anwendung abbrechen", + "cancelSuccess": "Vorverarbeitung erfolgreich abgebrochen.", + "toasts": { + "inProgressTitle": "Vorverarbeitung lĂ€uft", + "inProgressMsg": "Die Vorverarbeitung lĂ€uft derzeit. Fortschritt wird angezeigt...", + "cancelledTitle": "Vorverarbeitung abgebrochen", + "cancelledMsg": "Die Vorverarbeitung wurde abgebrochen.", + "cancellationFailedTitle": "Abbruch der Vorverarbeitung fehlgeschlagen", + "startedTitle": "Vorverarbeitung gestartet", + "startedMsg": "Die Vorverarbeitung wurde initiiert.", + "nowRunningMsg": "Die Vorverarbeitung lĂ€uft jetzt. Der Fortschritt wird im Modal angezeigt." + }, + "setupStepper": { + "title": "Skills anwenden", + "submitButton": "Skills anwenden", + "steps": { + "selectSkill": "Skill auswĂ€hlen", + "selectFiles": "Dateien auswĂ€hlen", + "selectBaseFiles": "Basisdateien auswĂ€hlen", + "confirmation": "BestĂ€tigung" + }, + "closeModalTitle": "Modal schließen", + "closeModalMessage": "Wenn Sie dieses Modal schließen, gehen Ihre aktuellen Auswahlen verloren. Möchten Sie wirklich fortfahren?" + }, + "processStepper": { + "steps": { + "progress": "Verarbeitungsfortschritt", + "confirmCancel": "Abbruch bestĂ€tigen" + }, + "stats": { + "processed": "Verarbeitet:", + "currentRuntime": "Aktuelle Laufzeit der Anfrage:", + "estimatedPerRequest": "GeschĂ€tzte Zeit pro Anfrage:", + "estimatedRemaining": "GeschĂ€tzte verbleibende Zeit:", + "calculating": "Wird berechnet...", + "almostDone": "Fast fertig..." + }, + "queue": { + "title": "Einreichungen in der Warteschlange", + "empty": "Keine Einreichungen in der Warteschlange. Die letzte Anfrage wird verarbeitet...", + "columns": { + "id": "ID", + "submissionName": "Name der Einreichung", + "user": "Benutzer" + } + }, + "cancel": { + "title": "Verarbeitung abbrechen", + "message": "Möchten Sie die verbleibenden Anfragen wirklich abbrechen?", + "confirmButton": "BestĂ€tigen", + "nextButton": "Weiter" + } + } + }, + "skills": { + "title": "Skills", + "status": { + "online": "ONLINE", + "offline": "OFFLINE", + "activating": "Aktivierung" + }, + "columns": { + "nodes": "# Knoten", + "activated": "Aktiviert", + "fallback": "Fallback" + }, + "toasts": { + "settingUpdatedTitle": "Einstellung aktualisiert", + "settingUpdatedMessage": "Aktivierung des Skills \"{name}\" aktualisiert.", + "updateFailedTitle": "Aktualisierung der Einstellung fehlgeschlagen" + } + } +} diff --git a/utils/modules/i18n/de/report.json b/utils/modules/i18n/de/report.json new file mode 100644 index 000000000..67f5b2198 --- /dev/null +++ b/utils/modules/i18n/de/report.json @@ -0,0 +1,10 @@ +{ + "noText": "(kein Text)", + "ref": "(vgl. {citation})", + "show": "(anzeigen)", + "reviewReport": "PrĂŒfbericht", + "emptyReport": "Leerer Bericht – keine Anmerkungen oder Kommentare gefunden.", + "generalComments": "Allgemeine Kommentare", + "noComments": "Keine Kommentare.", + "tip": "*Tipp: Bewegen Sie den Mauszeiger ĂŒber eine Referenz, um den referenzierten Text zu sehen, oder klicken Sie darauf, um die Anmerkung im PDF anzuzeigen." +} diff --git a/utils/modules/i18n/de/review.json b/utils/modules/i18n/de/review.json new file mode 100644 index 000000000..87fbf4d3c --- /dev/null +++ b/utils/modules/i18n/de/review.json @@ -0,0 +1,9 @@ +{ + "evaluateSession": "Diese Sitzung bewerten", + "sessionNotFinishedYet": "Diese Sitzung ist noch nicht beendet. Bitte warten Sie, bis sie geschlossen wurde!", + "thankYouForEvaluating": "Vielen Dank fĂŒr Ihre Bewertung dieser Sitzung!", + "sessionAlreadyEvaluated": "Diese Sitzung wurde bereits bewertet.", + "makeDecision": "Treffen Sie eine Entscheidung auf Basis dieser Sitzung.", + "comment": "Kommentar", + "acceptance": "Akzeptanz" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/settings.json b/utils/modules/i18n/de/settings.json new file mode 100644 index 000000000..40ec043c2 --- /dev/null +++ b/utils/modules/i18n/de/settings.json @@ -0,0 +1,19 @@ +{ + "title": "Einstellungen", + "changeUserSettings": "Benutzereinstellungen Ă€ndern", + "exportJson": "JSON exportieren", + "importJson": "JSON importieren", + "saveSettings": "Einstellungen speichern", + "saveSettingsUnsaved": "Einstellungen speichern (Ungespeicherte Änderungen)", + "importSettings": "Einstellungen importieren", + "rememberToSave": "Denken Sie daran, nach Änderungen auf \"Einstellungen speichern\" zu klicken.", + "importDescription": "WĂ€hlen Sie eine zuvor heruntergeladene Einstellungsdatei. Nur vorhandene SchlĂŒssel werden aktualisiert.", + "messages": { + "settingsLoaded": "Einstellungen geladen", + "settingsLoadedMessage": "Die Einstellungen wurden erfolgreich geladen.", + "settingsSavedSuccessfully": "Einstellungen wurden erfolgreich gespeichert.", + "settingsImported": "Einstellungen importiert.", + "updatedSettings": "{count} vorhandene Einstellungen aktualisiert.", + "unsavedChangesWarning": "Sie haben ungespeicherte Änderungen. Möchten Sie die Seite wirklich ohne Speichern verlassen?" + } +} diff --git a/utils/modules/i18n/de/sidebar.json b/utils/modules/i18n/de/sidebar.json new file mode 100644 index 000000000..801e4b626 --- /dev/null +++ b/utils/modules/i18n/de/sidebar.json @@ -0,0 +1,41 @@ +{ + "placeholders": "Platzhalter", + "textPlaceholder": "Text-Platzhalter", + "textPlaceholderDescription": "Inhaltblöcke hinzufĂŒgen", + "singleChart": "Einzeldiagramm", + "singleChartDescription": "Daten mit einem Diagramm visualisieren", + "comparisonChart": "Vergleichsdiagramm", + "comparisonChartDescription": "Mehrere DatensĂ€tze vergleichen", + "currentVersion": "Aktuelle Version", + "versionHistory": "Versionsverlauf", + "anonymousUser": "Anonymer Benutzer", + "periode": { + "today": "Heute", + "yesterday": "Gestern", + "thisWeek": "Diese Woche", + "lastWeek": "Letzte Woche", + "thisMonth": "Diesen Monat", + "lastMonth": "Letzten Monat", + "older": "Älter" + }, + "nav": { + "home": "Startseite", + "documents": "Dokumente", + "tags": "Tags", + "settings": "Einstellungen", + "logs": "Protokolle", + "studies": "Studien", + "study_sessions": "Studiensitzungen", + "users": "Benutzer", + "nlp_skills": "NLP-FĂ€higkeiten", + "user_stats": "Benutzerstatistiken", + "projects": "Projekte", + "submissions": "Einreichungen", + "review_documents": "Dokumentpruefung", + "configurations": "Konfigurationen", + "groups": { + "default": "Standard", + "admin": "Administrator" + } + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/studies.json b/utils/modules/i18n/de/studies.json new file mode 100644 index 000000000..141f0d7df --- /dev/null +++ b/utils/modules/i18n/de/studies.json @@ -0,0 +1,240 @@ +{ + "title": "Studien", + "study": "Studie", + "template": "Vorlage", + "sessions": "Sitzungen", + "savedTemplates": "Gespeicherte Vorlagen", + "closeAllStudies": "Alle Studien schließen", + "addBulkAssignments": "Sammelzuweisung hinzufĂŒgen", + "addSingleAssignment": "Zuweisung hinzufĂŒgen", + "editStudy": "Studie bearbeiten", + "deleteStudy": "Studie löschen", + "openStudy": "Studie öffnen", + "restartStudy": "Studie neustarten", + "closeStudy": "Studie schließen", + "copyLink": "Studien-Link kopieren", + "inspectSessions": "Sitzung prĂŒfen", + "saveAsTemplate": "Als Vorlage speichern", + "showInformation": "Informationen anzeigen", + "finishStudy": "Studie beenden", + "finishStudyAgain": "Studie erneut beenden", + "returnToDashboard": "Zum Dashboard zurĂŒckkehren", + "backToDashboard": "ZurĂŒck zum Dashboard", + "openSessions": "Offene Sitzungen", + "openSessionsForStudy": "Sitzungen fĂŒr {name} öffnen", + "resumeSession": "Sitzung fortsetzen", + "startSession": "Sitzung starten", + "joinStudy": "Studie beitreten", + "startStudy": "Studie starten", + "finishSession": "Sitzung beenden", + "sessionNotStarted": "Sitzung hat noch nicht begonnen", + "timeLeft": "Verbleibende Zeit", + "notStartedYet": "Die Studie ist noch nicht gestartet!", + "noMoreSessions": "Keine weiteren Sitzungen fĂŒr diese Studie verfĂŒgbar.", + "clickToStart": "Klicken Sie auf \"Benutzerstudie starten\", um zu beginnen.", + "collaborativeNote": "Dies ist eine kollaborative Studie. Alle Teilnehmer können gleichzeitig beitreten und arbeiten!", + "thankYouParticipation": "Vielen Dank fĂŒr Ihre Teilnahme :-)", + "canCloseBrowser": "Sie können den Browser jetzt schließen!", + "thankYouJoining": "Vielen Dank fĂŒr Ihre Teilnahme!", + "clickFinishToSubmit": "Mit einem Klick auf \"Beenden\" reichen Sie Ihre Ergebnisse ein.", + "timeExpired": "Die Zeit ist abgelaufen, es sind keine Änderungen mehr möglich.", + "nameOfStudy": "Name der Studie:", + "columns": { + "status": "Status", + "created": "Erstellt am", + "sessions": "Sitzungen", + "started": "Gestartet", + "finished": "Beendet", + "sessionLimit": "Sitzungslimit", + "sessionLimitPerUser": "Limit pro Nutzer", + "resumable": "Fortsetzbar", + "collaborative": "Kollaborativ", + "multipleSubmissions": "Mehrfacheinreichungen", + "timeLimit": "Zeitlimit" + }, + "status": { + "notStarted": "Nicht gestartet", + "running": "LĂ€uft", + "closed": "Geschlossen", + "ended": "Beendet" + }, + "messages": { + "studyStarted": "Studie gestartet", + "enjoy": "Viel Erfolg!", + "studyPublishedSuccess": "Studie erfolgreich veröffentlicht!", + "participantsCanJoin": "Teilnehmer können ĂŒber folgenden Link beitreten:", + "studyClosed": "Studie geschlossen", + "studyClosedMessage": "Die Studie wurde geschlossen", + "studyDeleted": "Studie gelöscht", + "studyDeletedMessage": "Die Studie wurde gelöscht", + "studyRestarted": "Studie neustarten", + "studyRestartedMessage": "Die Studie wurde neu gestartet", + "linkCopied": "Link kopiert", + "linkCopiedMessage": "Studien-Link in die Zwischenablage kopiert!", + "templateCreatedSuccess": "Vorlage erfolgreich erstellt!", + "templateCreated": "Vorlage erstellt", + "templateCreatedMessage": "Die Vorlage wurde erstellt.", + "templateSaved": "Vorlage gespeichert", + "templateSavedMessage": "Diese Studie wurde als Vorlage gespeichert.", + "deleteConfirm": "Sind Sie sicher, dass Sie die Studie löschen möchten?", + "deleteTitle": "Studie löschen", + "saveAsTemplateConfirm": "Sind Sie sicher, dass Sie diese Studie als Vorlage speichern möchten?", + "saveAsTemplateTitle": "Studie als Vorlage speichern", + "studyFinished": "Diese Studie wurde am {date} beendet", + "studyStartDate": "Start: {date}", + "timeLimitNote": "Bitte beachten Sie das Zeitlimit von {minutes} Min. fĂŒr diese Studie!", + "sessionsLeft": "Sie haben noch {count} Sitzungen fĂŒr diese Studie ĂŒbrig.", + "sessionWarning": "Es existieren derzeit {count} Sitzungen fĂŒr diese Studie. Das Löschen der Studie entfernt auch diese Sitzungen!", + "sessionFinished": "Sitzung beendet", + "sessionFinishedMessage": "Ihre Sitzung wurde erfolgreich eingereicht.", + "studySessionErrorTitle": "Fehler in der Studiensitzung" + }, + "loading": { + "title": "Lade Studienschritt", + "nlpError": "Fehler bei der Verarbeitung der NLP-Ergebnisse. Bitte versuchen Sie es erneut oder ĂŒberspringen Sie die NLP-UnterstĂŒtzung.", + "generalError": "Beim Laden des Studienschritts ist ein Fehler aufgetreten. Bitte versuchen Sie es spĂ€ter erneut.", + "buttons": { + "tryAgain": "Erneut versuchen", + "skip": "NLP-UnterstĂŒtzung ĂŒberspringen" + }, + "messages": [ + "Denke ĂŒber Ihre Anfrage nach...", + "Fast fertig, verfeinere die Details...", + "Suche die bestmögliche Antwort...", + "Nur noch einen Moment, PrĂ€zision braucht Zeit...", + "Arbeite an einer schlauen Lösung...", + "Einen Augenblick... ich denke schneller, als es aussieht...", + "Ordne kurz die Neuronen neu...", + "ZĂŒnde ein wenig Sprachmagie...", + "Ihre Anfrage reist durch eine Milliarde Neuronen...", + "Suche in allen Ecken nach AusnahmefĂ€llen...", + "Mache einen schnellen PlausibilitĂ€tscheck...", + "Konsultiere die Weisheit der Menge...", + "Fast geschafft..." + ] + }, + "dashboard": { + "activeSessions": { + "title": "Aktive Studiensitzungen", + "noSessions": "Sie haben keine aktiven Studiensitzungen. Rufen Sie eine Studie ĂŒber den Link auf oder erstellen Sie eine eigene Studie." + }, + "closedSessions": { + "title": "Geschlossene Studiensitzungen", + "noSessions": "Sie haben keine geschlossenen Studiensitzungen." + }, + "studyTitle": "Studie: {name}", + "studyTitleWithAuthor": "Studie: {name} (von {author})", + "noName": "", + "noDueDate": "keine Frist" + }, + "modalTitle": { + "createTemplate": "Vorlage erstellen", + "editTemplate": "Vorlage bearbeiten", + "newTemplate": "Neue Vorlage", + "createStudy": "Studie erstellen", + "editStudy": "Studie bearbeiten", + "newStudy": "Neue Studie" + }, + "unit": { + "sessions": "Sitzung(en)" + }, + "form": { + "name": { + "label": "Name der Studie", + "placeholder": "Meine Nutzerstudie" + }, + "workflow": { + "label": "Workflow fĂŒr die Studie auswĂ€hlen", + "help": "WĂ€hlen Sie eine Workflow-Vorlage fĂŒr die einzelnen Studienschritte aus." + }, + "tagSet": { + "label": "Tag-Set fĂŒr die Studie", + "help": "WĂ€hlen Sie ein Tag-Set aus, das in dieser Studie verwendet werden soll." + }, + "stepDocuments": { + "label": "Dokumente den Workflow-Schritten zuordnen" + }, + "description": { + "label": "Beschreibung der Studie", + "help": "Dieser Text wird den Teilnehmenden zu Beginn der Studie angezeigt." + }, + "timeLimit": { + "label": "Wie viel Zeit steht den Teilnehmenden fĂŒr die Studie zur VerfĂŒgung?", + "help": "Legen Sie die maximale Bearbeitungszeit fest. Verwenden Sie 0, um das Zeitlimit zu deaktivieren." + }, + "limitSessions": { + "label": "Anzahl der Sitzungen fĂŒr die Studie begrenzen", + "help": "Legen Sie fest, wie oft Teilnehmende die Studie starten oder fortsetzen dĂŒrfen. Verwenden Sie 0 fĂŒr eine unbegrenzte Anzahl an Sitzungen." + }, + "limitSessionsPerUser": { + "label": "Anzahl der Sitzungen pro Person begrenzen", + "help": "Legen Sie fest, wie oft jede teilnehmende Person die Studie starten oder fortsetzen darf. Verwenden Sie 0 fĂŒr unbegrenzte Sitzungen." + }, + "collab": { + "label": "Soll die Studie kollaborativ sein?" + }, + "anonymize": { + "label": "Sollen Kommentare anonymisiert werden?" + }, + "resumable": { + "label": "Soll die Studie fortsetzbar sein?" + }, + "multipleSubmit": { + "label": "Mehrfache Abgaben erlauben?", + "help": "Legen Sie fest, ob Teilnehmende die Studie mehr als einmal abschicken dĂŒrfen." + }, + "start": { + "label": "Studien-Sitzungen dĂŒrfen nicht starten vor" + }, + "end": { + "label": "Studien-Sitzungen dĂŒrfen nicht starten nach" + } + }, + "workflowConfig": { + "addLinkEod": { + "reviewLink": { + "help": "Der Link wird am Ende des Dokuments angehĂ€ngt. `~SESSION_HASH~` wird durch den aktuellen Sitzungs-Hash ersetzt." + }, + "reviewText": { + "help": "Finden Sie das Feedback hilfreich?" + } + }, + "assessment": { + "configurationId": { + "label": "Bewertungs-Konfigurationsdatei:", + "help": "WĂ€hlen Sie die Konfigurationsdatei fĂŒr diesen Workflow-Schritt zur Bewertung aus." + }, + "forcedAssessment": { + "label": "Erzwungene Bewertung", + "help": "Wenn aktiviert, mĂŒssen Reviewer fĂŒr jedes Kriterium eine Punktzahl und BegrĂŒndung speichern, bevor sie fortfahren können." + } + }, + "assessmentWithAi": { + "configurationId": { + "label": "Konfigurationsdatei:", + "help": "WĂ€hlen Sie die Konfigurationsdatei fĂŒr diesen Workflow-Schritt aus." + }, + "forcedAssessment": { + "label": "Erzwungene Bewertung", + "help": "Wenn aktiviert, mĂŒssen Reviewer fĂŒr jedes Kriterium eine Punktzahl und BegrĂŒndung speichern, bevor sie fortfahren können." + } + }, + "modalSize": { + "label": "ModalgrĂ¶ĂŸe", + "options": { + "small": "Klein", + "medium": "Mittel", + "large": "Groß", + "extraLarge": "Sehr groß" + } + } + }, + "workflow": { + "peer_review_workflow": "Peer-Review-Workflow", + "peer_review_workflow_(assessment)": "Peer-Review-Workflow (Bewertung)", + "peer_review_workflow_(assessment_with_ai)": "Peer-Review-Workflow (Bewertung mit KI)", + "ruhr-uni_bochum_project": "Ruhr-Uni Bochum Projekt", + "ruhr-uni_bochum_project_control": "Ruhr-Uni Bochum Projekt (Kontrolle)", + "annotation_workflow": "Anmerkungs-Workflow" + } +} diff --git a/utils/modules/i18n/de/submission.json b/utils/modules/i18n/de/submission.json new file mode 100644 index 000000000..9eb85096b --- /dev/null +++ b/utils/modules/i18n/de/submission.json @@ -0,0 +1,56 @@ +{ + "dashboard": { + "title": "Einreichungen", + "buttons": { + "assignGroup": "Gruppe zuweisen", + "publishReviews": "Bewertungen veröffentlichen", + "publishSubmissions": "Einreichungen veröffentlichen", + "manualImport": "Manueller Import", + "importMoodle": "Import ĂŒber Moodle", + "viewProcessing": "Verarbeitung anzeigen", + "applySkills": "FĂ€higkeiten anwenden" + }, + "tooltips": { + "assignGroup": "Gruppe zuweisen", + "publishReviews": "Bewertungen veröffentlichen", + "publishSubmissions": "Einreichungen veröffentlichen", + "manualImport": "Manueller Import", + "importMoodle": "Import ĂŒber Moodle", + "viewProcessing": "Verarbeitungsfortschritt anzeigen", + "applySkills": "FĂ€higkeiten anwenden", + "processingActive": "Verarbeitung aktiv" + }, + "columns": { + "id": "ID", + "firstName": "Vorname", + "lastName": "Nachname", + "submissionId": "Einreichungs-ID", + "group": "Gruppe", + "validationId": "Validierungs-ID", + "createdAt": "Erstellt am" + }, + "actions": { + "download": "Einreichungsdateien herunterladen", + "delete": "Dokument löschen..." + }, + "delete": { + "title": "Dokument löschen", + "message": "Möchten Sie das Dokument wirklich löschen?", + "warning": "Auf diesem Dokument lĂ€uft derzeit {count} Studie. Das Löschen wird die Studie löschen! | Auf diesem Dokument laufen derzeit {count} Studien. Das Löschen wird die Studien löschen!" + }, + "toasts": { + "deleteSuccessTitle": "Dokument gelöscht", + "deleteSuccessMessage": "Das Dokument wurde gelöscht", + "deleteFailedTitle": "Löschen fehlgeschlagen", + "noDocumentsTitle": "Keine Dokumente gefunden", + "noDocumentsMessage": "Diese Einreichung hat keine zugeordneten Dokumente zum Herunterladen", + "downloadIssueTitle": "Dokumentdownload-Problem", + "downloadIssueMessage": "Konnte {name} nicht herunterladen", + "downloadErrorTitle": "Download-Fehler", + "downloadErrorMessage": "Fehler beim Herunterladen von {name}: {error}", + "downloadCompleteTitle": "Download abgeschlossen", + "downloadCompleteMessage": "Einreichung {id} mit {count} Dokumenten heruntergeladen", + "downloadFailedTitle": "Download fehlgeschlagen" + } + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/tagSelector.json b/utils/modules/i18n/de/tagSelector.json new file mode 100644 index 000000000..f6414a3f3 --- /dev/null +++ b/utils/modules/i18n/de/tagSelector.json @@ -0,0 +1,6 @@ +{ + "chooseTag": "WĂ€hlen Sie ein Tag aus...", + "selectTag": "Bitte wĂ€hlen Sie ein gĂŒltiges Tag aus.", + "addTag": "Tag hinzufĂŒgen...", + "noTags": "Keine Tags" +} \ No newline at end of file diff --git a/utils/modules/i18n/de/tags.json b/utils/modules/i18n/de/tags.json new file mode 100644 index 000000000..66bc9e16c --- /dev/null +++ b/utils/modules/i18n/de/tags.json @@ -0,0 +1,74 @@ +{ + "title": "Tag-Sets", + "tagSet": "Tag-Set", + "addNewTagSet": "Neues Tag-Set hinzufĂŒgen", + "copyTagSet": "Tag-Set kopieren", + "editTagSet": "Tag-Set bearbeiten", + "deleteTagSet": "Tag-Set löschen", + "shareTagSet": "Tag-Set freigeben", + "selectAsDefault": "Tag-Set als Standard auswĂ€hlen", + "modalTitle": { + "newTagSet": "Neues Tag-Set", + "editTagSet": "Tag-Set bearbeiten" + }, + "columns": { + "tags": "Tags", + "lastChange": "Letzte Änderung", + "user": "Benutzer" + }, + "messages": { + "deleteTitle": "Tag-Set löschen", + "deleteConfirm": "Möchten Sie das Tag-Set wirklich löschen?", + "tagSetDeleted": "Tag-Set gelöscht", + "tagSetDeletedMessage": "Das Tag-Set wurde erfolgreich gelöscht", + "publishTitle": "Tag-Set veröffentlichen", + "publishConfirm": "Möchten Sie das Tag-Set wirklich veröffentlichen? Hinweis: Nach der Veröffentlichung können Sie das Tag-Set nicht mehr rĂŒckgĂ€ngig machen!", + "tagSetPublished": "Tag-Set veröffentlicht", + "tagSetPublishedMessage": "Das Tag-Set wurde erfolgreich veröffentlicht" + }, + "form": { + "name": { + "label": "Name des Tag-Sets:", + "placeholder": "Mein Tag-Set" + }, + "description": { + "label": "Beschreibung des Tag-Sets:", + "placeholder": "Tag-Set-Beschreibung" + }, + "tags": { + "label": "Tags:" + } + }, + "editMainTag": "Haupt-Tag bearbeiten", + "basicTags": { + "highlight": "Hervorheben", + "strength": "StĂ€rke", + "weakness": "SchwĂ€che", + "other": "Sonstiges" + }, + "basicTagGroups": { + "peerReview": "Peer Review", + "standardSet": "Ein Standard-Tagset fĂŒr den Peer-Review-Prozess" + }, + "tag":{ + "form": { + "name":{ + "label": "Name", + "placeholder": "Name des Tags" + }, + "description": { + "label": "Beschreibung", + "placeholder":"Beschreibung des Tags" + }, + "colorCode": { + "label": "Farbe", + "options": { + "info": "Info", + "warning": "Warnung", + "success": "Erfolg", + "danger": "Gefahr" + } + } + } + } +} \ No newline at end of file diff --git a/utils/modules/i18n/de/users.json b/utils/modules/i18n/de/users.json new file mode 100644 index 000000000..e36567786 --- /dev/null +++ b/utils/modules/i18n/de/users.json @@ -0,0 +1,82 @@ +{ + "title": "Benutzer", + "downloadUsers": "Benutzer herunterladen", + "assignRoles": "Rollen zuweisen", + "uploadPassword": "Passwort hochladen", + "importCsv": "CSV importieren", + "importViaMoodle": "Import ĂŒber Moodle", + "addUser": "Benutzer hinzufĂŒgen", + "editUser": "Benutzer bearbeiten", + "viewRights": "Rechte anzeigen", + "resetPassword": "Passwort zurĂŒcksetzen", + "deleteUser": "Benutzer löschen", + "columns": { + "firstName": "Vorname", + "lastName": "Nachname", + "userName": "Benutzer", + "email": "E-Mail", + "acceptTerms": "Bedingungen akzeptiert", + "acceptStats": "Statistiken akzeptiert", + "acceptDataSharing": "Datenaustausch akzeptiert", + "verified": "Verifiziert", + "lastLogin": "Letzte Anmeldung" + }, + "messages": { + "deleteConfirm": "Möchten Sie diesen Benutzer wirklich löschen?", + "deleteTitle": "Benutzer löschen", + "userDeleted": "Benutzer gelöscht", + "userDeletedMessage": "Der Benutzer wurde gelöscht" + }, + "stats": { + "exportCsv": "Als CSV exportieren", + "exportJson": "Als JSON exportieren", + "userStatsTitle": "Statistiken fĂŒr {count} Benutzer | Statistiken fĂŒr {count} Benutzer", + "columns": { + "user": "Benutzer", + "id": "ID", + "lastLogin": "Letzte Anmeldung", + "time": "Zeit", + "action": "Aktion", + "data": "Daten" + }, + "toasts": { + "exportFailedTitle": "Export fehlgeschlagen", + "exportFailedMessage": "Export fehlgeschlagen." + } + }, + "roles": { + "teacher": "Lehrer", + "mentor": "Tutor", + "student": "Student", + "guest": "Gast", + "user": "Benutzer", + "admin": "Administrator" + }, + "rightDescriptions": { + "backend_socket_user_getUsers_student": "Zugriff auf alle Studierenden", + "backend_socket_user_getUsers_mentor": "Zugriff auf alle Mentor:innen", + "frontend_dashboard_users_view": "Zugriff auf die Benutzeransicht im Dashboard", + "backend_socket_user_getUsers_all": "Zugriff auf alle Benutzer", + "frontend_dashboard_studies_addBulkAssignments": "Zugriff auf das Massenhinzufugen von Zuweisungen im Dashboard", + "frontend_dashboard_studies_addSingleAssignments": "Zugriff auf das Hinzufugen von Zuweisungen im Dashboard", + "frontend_dashboard_studies_fullAccess": "Zugriff auf offene Studien und Sitzungen", + "frontend_dashboard_studies_view_readOnly": "Zugriff auf Sitzungen im Nur-Lesen-Modus", + "frontend_dashboard_studies_view_userPrivateInfo": "Zugriff auf private Benutzerinformationen wie Vor- und Nachname", + "frontend_dashboard_home_view": "Zugriff auf die Startseite im Dashboard", + "frontend_dashboard_documents_view": "Zugriff auf Dokumente im Dashboard", + "frontend_dashboard_tags_view": "Zugriff auf Tag-Sets im Dashboard", + "frontend_dashboard_projects_view": "Zugriff auf Projekte im Dashboard", + "frontend_dashboard_studies_view": "Zugriff auf Studien im Dashboard", + "frontend_dashboard_study_sessions_view": "Zugriff auf Studiensitzungen im Dashboard", + "study_template_delete": "Zugriff auf das Loschen von Vorlagen" + }, + "roleDescriptions": { + "admin": "Vollzugriff", + "user": "Keine Systemrechte", + "teacher": "Verantwortlich fur Koordination", + "mentor": "Hat das Recht zu benoten", + "student": "Verfasst Inline-Kommentare", + "guest": "Hat eingeschrankte Rechte bei der Nutzung der Plattform", + "system": "Systembenutzer" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/annotator.json b/utils/modules/i18n/en/annotator.json new file mode 100644 index 000000000..ee89f5134 --- /dev/null +++ b/utils/modules/i18n/en/annotator.json @@ -0,0 +1,20 @@ +{ + "documentNote": "Document Note", + "createdByUser": "Created by User {userId}", + "messages": { + "unsavedAnnotations": "Unsaved Annotations", + "unsavedAnnotationsWarning": "Are you sure you want to leave the annotator? There are unsaved annotations, which will be lost." + }, + "annotations": "Annotations", + "submitReview": "Submit Review", + "report": "Report", + "accept": "Accept", + "reject": "Reject", + "hideStudyComments": "Hide study comments", + "showStudyComments": "Show study comments", + "deactivateNlpSupport": "Deactivate NLP support", + "activateNlpSupport": "Activate NLP support", + "downloadAnnotations": "Download Annotations", + "documentSubscribeError": "Document subscribe error", + "replies": "Replies" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/assessment.json b/utils/modules/i18n/en/assessment.json new file mode 100644 index 000000000..041beea8d --- /dev/null +++ b/utils/modules/i18n/en/assessment.json @@ -0,0 +1,21 @@ +{ + "title": "Assessment", + "noConfiguration": "No Assessment Configuration available.", + "totalPoints": "{points} P", + "criteria": { + "unnamedCriterion": "Unnamed criterion", + "justification": "Justification:", + "noJustification": "No justification provided", + "editPlaceholder": "Edit the justification...", + "edit": "Edit", + "changeScore": "Change score", + "saved": "Assessment saved", + "save": "Save assessment", + "saveEdit": "Save", + "cancel": "Cancel" + }, + "rubric": { + "unnamedRubric": "Unnamed rubric", + "noCriteria": "No criteria defined for this rubric." + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/auth.json b/utils/modules/i18n/en/auth.json new file mode 100644 index 000000000..41be7424d --- /dev/null +++ b/utils/modules/i18n/en/auth.json @@ -0,0 +1,56 @@ +{ + "login": "Login", + "logout": "Logout", + "register": "Register", + "username": "Username", + "password": "Password", + "email": "E-Mail", + "emailAddress": "Email Address", + "firstName": "First name", + "lastName": "Last name", + "forgotPassword": "Forgot Password?", + "resetPassword": "Reset Password", + "changePassword": "Change password", + "currentPassword": "Current Password", + "newPassword": "New Password", + "confirmPassword": "Confirm Password", + "loginAsGuest": "Login as Guest", + "usernameOrEmail": "Username or email", + "signedInAs": "Signed in as {username}", + "updateConsent": "Update consent", + "termsOfService": "Terms of Service", + "acceptTerms": "I accept the Terms of Service", + "acceptStats": "I allow the collection of anonymous statistics", + "acceptDataSharing": "I agree to my data being made available for research purposes", + "acceptStatsBehavior": "I allow the collection of behaviour statistics for research purpose", + "acceptAndContinue": "Accept & Continue", + "emailVerificationRequired": "Email Verification Required", + "resendVerificationEmail": "Resend Verification Email", + "returnToLogin": "Return to Login", + "backToLogin": "Back to Login", + "placeholders": { + "newPasswordPlaceholder": "Enter new password (minimum 8 characters)", + "confirmPasswordPlaceholder": "Confirm new password" + }, + "messages": { + "emailVerified": "Email Verified", + "emailVerifiedSuccess": "Your email has been successfully verified. You can now log in.", + "resetTokenValid": "Token is valid.", + "validationLinkSent": "A validation link was sent to your email", + "validateEmail": "Validate your email", + "registrationSuccess": "Registration successful! You can now log in.", + "logoutSuccess": "Session ended.", + "passwordResetLinkSent": "Password reset link has been sent to your email address.", + "passwordResetInstructions": "We'll send password reset instructions to this email address.", + "emailNotVerified": "Your email address has not been verified yet. Please check your inbox for a verification email.", + "resendVerificationPrompt": "Didn't receive the email? Click the button below to resend.", + "verificationEmailSent": "Verification email has been sent successfully.", + "validatingResetToken": "Validating reset token...", + "passwordResetSuccess": "Password has been successfully reset. You can now login with your new password.", + "termsUpdated": "Terms successfully updated.", + "termsUpdatedMessage": "The terms have been successfully updated.", + "consentUpdated": "Consent successfully updated", + "consentUpdatedMessage": "The consent settings were updated successfully" + }, + "copyright": "Copyright © 2022-2024 Team Care UKP Lab (TU Darmstadt)" +} diff --git a/utils/modules/i18n/en/basic.json b/utils/modules/i18n/en/basic.json new file mode 100644 index 000000000..1faedbfc9 --- /dev/null +++ b/utils/modules/i18n/en/basic.json @@ -0,0 +1,68 @@ +{ + "form": { + "placeholders": { + "documentBracket": "" + } + }, + "configuration": { + "title": "Configuration", + "filesTitle": "Configuration Files", + "uploadButton": "Upload Configuration", + "uploadTooltip": "Upload new configuration file", + "types": { + "assessment": "Assessment", + "validation": "Validation" + }, + "viewer": { + "title": "Configuration: {name}" + }, + "editor": { + "title": "Edit Configuration: {name}", + "placeholder": "Edit JSON content here..." + }, + "delete": { + "title": "Delete Configuration", + "message": "Are you sure you want to delete \"{name}\"?" + }, + "tooltips": { + "view": "View configuration", + "edit": "Edit configuration", + "delete": "Delete configuration" + }, + "steps": { + "general": "General Settings", + "services": "Services", + "placeholders": "Placeholders" + }, + "editButton": "Edit Configuration", + "saveButton": "Save Configuration", + "toasts": { + "updatedTitle": "Configuration Updated", + "updatedMessage": "The configuration data has been successfully updated.", + "loadErrorTitle": "Configuration Error", + "loadErrorMessage": "Failed to load configuration content: {error}", + "editorNotInit": "Editor not initialized", + "noContent": "No configuration content to save", + "invalidJsonTitle": "Invalid JSON", + "invalidJsonMessage": "Please check your JSON syntax: {error}", + "updateErrorTitle": "Configuration Update Error", + "updateErrorMessage": "Failed to update configuration", + "deleteFailedTitle": "Configuration delete failed" + }, + "stepTitles": { + "general": "General Configuration", + "services": "Services Configuration", + "placeholders": "Placeholders Configuration" + } + }, + "consent": { + "successTitle": "Consent successfully updated", + "successMessage": "The consent settings have been successfully updated.", + "errorTitle": "Error updating consent" + + }, + "export": { + "successTitle": "Export Success", + "successMessage": "Exported {id}" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/common.json b/utils/modules/i18n/en/common.json new file mode 100644 index 000000000..f6a588353 --- /dev/null +++ b/utils/modules/i18n/en/common.json @@ -0,0 +1,119 @@ +{ + "yes": "Yes", + "no": "No", + "ok": "OK", + "save": "Save", + "cancel": "Cancel", + "close": "Close", + "abort": "Abort", + "decline": "Decline", + "confirm": "Confirm", + "back": "Back", + "previous": "Previous", + "next": "Next", + "nextText": "nextText", + "new": "New", + "add": "Add", + "create": "Create", + "edit": "Edit", + "editItem": "Edit {item}", + "change": "Change", + "update": "Update", + "delete": "Delete", + "copy": "Copy", + "download": "Download", + "upload": "Upload", + "import": "Import", + "export": "Export", + "reload": "Reload", + "loading": "Loading...", + "noData": "No data", + "success": "Success", + "error": "Error", + "warning": "Warning", + "info": "Info", + "readOnly": "Read Only", + "id": "ID", + "name": "Name", + "title": "Title", + "createdAt": "Created At", + "updatedAt": "Last Change", + "type": "Type", + "status": "Status", + "public": "Public", + "actions": "Actions", + "manage": "Manage", + "search": "Search", + "filter": "Filter", + "sortBy": "Sort By", + "page": "Page", + "of": "of", + "show": "Show", + "start": "Start", + "end": "End", + "created": "Created", + "user": "User", + "userName": "User Name", + "userId": "User Id", + "email": "Email", + "extId": "extId", + "firstName": "First Name", + "lastName": "Last Name", + "groupId": "Group ID", + "dataExisting": "Data Existing", + "loadingFromServer": "Loading data from server...", + "typeToFilter": "Type to filter table...", + "submitText": "submitText", + "required": "This field is required", + "select": "Select", + "baseFileType": "Select base file type:", + "example": "Example", + "input": "Input", + "output": "Output", + "config": "Config", + "send": "Send", + "note": "Note:", + "stepper": { + "stepNotImplemented": "Step {step} is not implemented." + }, + "itemsPerPage": "Items per page", + "all": "All", + "label": "Pagination", + "assign": "Assign", + "confirmation": "Confirmation", + "project": "Project", + "language": "Language", + "reset": "Reset", + "na": "N/A", + "time": { + "seconds": "{sec}s", + "minutesSeconds": "{min}m {sec}s", + "hoursMinutesSeconds": "{h}h {min}m {sec}s", + "minutes": "min" + }, + + "reply": "Reply", + "hide": "Hide", + "showMore": "Show more", + "showLess": "Show less", + "hideMore": "Hide more", + "summarize": "Summarize", + "apply": "Apply", + "unknown": "Unknown", + "submission": "Submission", + "assignments": "Assignments", + "use": "Use", + "hideReplies": "Hide replies", + "connecting": "Connecting...", + "loadingProgress": "Load {appLoadStep} ({percent}%)", + "duplicate": "Duplicate", + "notSet": "Not yet set", + "details": "Details", + "view": "View", + "updated": "Updated", + "refresh": "Refresh", + "configure": "Configure", + "anonymous": "Anonymous", + "unlimited": "unlimited" + +} \ No newline at end of file diff --git a/utils/modules/i18n/en/components.json b/utils/modules/i18n/en/components.json new file mode 100644 index 000000000..9d322d47a --- /dev/null +++ b/utils/modules/i18n/en/components.json @@ -0,0 +1,32 @@ +{ + "logs":{ + "title": "Logs", + "columns": { + "level": "Level", + "time": "Time", + "service": "Service", + "message": "Message" + }, + "levels": { + "error": "Error", + "warn": "Warning", + "info": "Info", + "debug": "Debug" + } + }, + "comment":{ + "enterText": "Enter text...", + "noComment": "No comment", + "sentimentAnalysis": "Sentiment Analysis", + "saveCommand": "Save (Ctrl+Enter)" + }, + "voteButtons":{ + "helpful": "Helpful", + "notHelpful": "Not helpful" + }, + "pdftoolbar":{ + "minToolbar": "Minimize Toolbar", + "showToolbar": "Show Toolbar" + } + +} \ No newline at end of file diff --git a/utils/modules/i18n/en/coordinator.json b/utils/modules/i18n/en/coordinator.json new file mode 100644 index 000000000..a21d56c08 --- /dev/null +++ b/utils/modules/i18n/en/coordinator.json @@ -0,0 +1,10 @@ +{ + "entryUpdated": "The entry has been updated successfully!", + "entryAdded": "The entry has been added successfully!", + "errors": { + "noFieldsDefined": "The table {table} has no defined fields!", + "saveFailed": "Could not save", + "incompleteConfig": "Incomplete Configuration", + "incompleteConfigDetail": "You have incomplete configuration at {steps}" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/dashboard.json b/utils/modules/i18n/en/dashboard.json new file mode 100644 index 000000000..f393f8a36 --- /dev/null +++ b/utils/modules/i18n/en/dashboard.json @@ -0,0 +1,392 @@ +{ + "projects": { + "title": "Projects", + "assignProjectsToUsers": "Assign Projects to users", + "selectProjectToAssign": "Select project to assign:", + "OneProjectSelected": "1 project selected", + "ZeroProjectsSelected": "0 projects selected", + "selectUsersToAssignProjectsTo": "Select users to assign projects to:", + "usersSelected": "user(s) selected", + "confirmAssignment": "Confirm assignment:", + "summary": "Summary:", + "aboutToAssign": "You are about to assign {projectCount} project to {userCount} user(s).", + "noteLabel": "Note:", + "noteBody": "By assigning users to this project, the project will automatically be made public.", + "selectedProjects": "Selected projects:", + "selectedUsers": "Selected users:", + "selectProjects": "Select projects", + "selectUsers": "Select users", + "selectProject": "Select Project", + "assignmentFailed": "Assignment failed", + "selectMessage": "Please select a project and at least one user.", + "projectAssignmentFailed": "Project assignment failed", + "projectAssigned": "Project assigned", + "successfullyAssignedMessage": "The project has been successfully assigned to {count} user(s).", + "exportData": "Export Data", + "exportStudySessions": "Exporting a list of all study sessions with hash:", + "totalStudies": "Total Studies:", + "totalStudySessions": "Total Study Sessions:", + "exportingAllData": "Exporting all data", + "totalTags": "Total Tags:", + "totalTagSets": "Total Tag Sets:", + "totalProjects": "Total Projects:", + "totalDocuments": "Total Documents:", + "totalAnnotations": "Total Annotations:", + "totalComments": "Total Comments:", + "totalCommentsVotes": "Total Comment Votes:", + "totalEdits": "Total Edits:", + "exportType": "Export Type", + "exportReviewers": "Export a list of all reviewers", + "extId": "extId", + "numberOfAssignments": "Number of Assignments", + "roles": "Roles", + "filterTable": "From which should be filtered?", + + "createTooltip": "Create project", + "assignButton": "Assign projects", + "assignTooltip": "Assign projects", + "coordinator": { + "title": "Project" + }, + "columns": { + "name": "Project name", + "public": "Public", + "closed": "Closed" + }, + "actions": { + "copy": "Copy project", + "edit": "Edit project", + "delete": "Delete project", + "share": "Share project", + "export": "Export data", + "selectDefault": "Select project as default" + }, + "delete": { + "title": "Delete Project", + "message": "Are you sure you want to delete this project?", + "warningStudies": "There is currently {count} study linked to this project. Deleting the project will also delete the study. | There are currently {count} studies linked to this project. Deleting the project will also delete the studies.", + "warningDocuments": "There is currently {count} document linked to this project. Deleting the project will also delete the document. | There are currently {count} documents linked to this project. Deleting the project will also delete the documents." + }, + "toasts": { + "deleteFailed": "Project delete failed", + "publishFailed": "Project publish failed", + "publishedTitle": "Project published", + "publishedMessage": "The project has been successfully published." + }, + "fields": { + "name": { + "label": "Name of the project:", + "placeholder": "My project" + }, + "description": { + "label": "Description of the project:", + "placeholder": "My project description" + }, + "publicSwitch": "Is the project public?" + } + }, + "settings": { + "selectSetting": "Select setting", + "selectedValue": "Selected Value:", + "usersSelected": "user(s) selected", + "setting:": "Setting:", + "newValue": "New Value:", + "users:": "Users:", + "noteBody1": "This will update the selected per-user setting for all chosen users. It does not change the global default setting.", + "setting": "Setting", + "selectedUsers": "Selected Users", + "updateFailed": "Update failed", + "selectSettingAndUser": "Please select a setting and at least one user.", + "settingsUpdated": "Settings updated", + "updatedMessage": "Updated \"{key}\" for {count} user(s).", + "mainSettings": "Main settings of the application", + "sensitiveDataNote": "Note: Make sure that no sensitive data are present!", + "toolbarNote": "Note: When the toolbar is disabled, all the tools will be hidden!", + "nlpSupport": "Activate/Deactivate NLP support" + }, + "study": { + "addSingleAssignment": "Add Single Assignment", + "addReviewer": "Add Reviewer", + "addReviewers": "Add Reviewers", + "reviewersAdded": "Reviewers added", + "reviewersAddedMessage": "The reviewers have been added successfully", + "failedToAddReviewers": "Failed to add reviewers", + "createBulkAssignment": "Create bulk assignment", + "noStudyTemplatesAvailable": "There are no study templates available!", + "createTemplateToProceed": "Please create a study template to proceed!", + "workflowSteps": "Workflow Steps:", + "workflowStepWithIndex": "Workflow Step {index}:", + "assignmentBase": "Assignment should be based on:", + "annotator": "Annotator", + "editor": "Editor", + "filterUsersWithDocuments": "Filter only users with documents", + "filterUsersFromPreviousDocuments": "Filter only users from previous selected documents", + "defineTheNumberOfReviews": "Define the number of reviews that each user of the role should perform:", + "noRolesAvailable": "There are no roles available!", + "selectReviewersOrChangeMode": "Please select reviewers with roles or change selection mode!", + "discontributeDocuments": "Distribute the documents between the selected reviewers:", + "remainingAssignments": "Remaining Assignments:", + "selectMode": "Please select a reviewer selection mode", + "createAssignmentConfirmPrompt": "Are you sure you want to create the assignment with the following details?", + "warning": "Warning:", + "notReviewOwnDocument": "The assignment process will make sure that a reviewer not reviews their own document.", + "warning1": "This could lead to a failure in the assignment process,", + "warning2": "so make sure that the values are set correct for a successful assignment.", + "template": "Template:", + "workflow": "Workflow:", + "documents": "Documents:", + "reviewers": "Reviewers:", + "reviewsToCreate": "Reviews to create:", + "selectionMode": "Selection Mode:", + "roles": "Roles:", + "submissionWithId": "Submission {id}", + "templateSelection": "Template Selection", + "documentSelection": "Document Selection", + "reviewerSelection": "Reviewer Selection", + "distribution": "Distribution", + "reviewerSelectionMode": "Reviewer Selection Mode", + "roleBasedSelection": "Role-based selection (the number of documents that should be reviewed by each user of the selected roles)", + "reviewerBasedSelection": "Reviewer-based selection (distribute document between the selected reviewers)", + "nameOfReviewsForRole": "Number of reviews for role: ", + "nameofReviewsForUsers": "Number of reviews for user: ", + "reviews": "review(s)", + "assignmentCreated": "Assignment created", + "assignmentCreatedMessage": "The assignment has been created successfully", + "failedToCreateAssignment": "Failed to create assignment", + "bulkCloseStudies": "Bulk Close Studies", + "closeStudiesPrompt": "Are you sure you want to close all open studies?", + "allStudiesClosed": "All studies closed", + "closeAllStudies": "Close All Studies", + "allStudiesClosedMessage": "All open studies have been closed", + "failedToClose": "Failed to close all studies", + "createTemplate": "Create Template", + "deleteTemplate": "Delete Template", + "deleteTemplatePrompt": "Are you sure you want to delete this template?", + "studyTemplateDeleted": "Study template deleted", + "studyTemplateDeletedMessage": "The study template has been deleted", + "deletionFailed": "Study template deletion failed", + "assignmentType": "Assignment Type:", + "workflowAssignments": "Workflow Assignments:", + "createAssignment": "Create Assignment", + "assignmentSelection": "Assignment Selection", + "studySessionsOf": "Study Sessions of", + "openSession": "Open session", + "inspectSession": "Inspect session", + "copySessionLink": "Copy session link", + "deleteSession": "Delete session", + "notYet": "not yet", + "deleteSessionNote": "You are about to delete a session; if you just want to finish the session, please access the session and abort the delete.", + "studySessionDeleted": "Study Session deleted", + "studySessionHasBeenDeleted": "Study session has been deleted", + "studySessionNotDeleted": "Study Session not deleted", + "studySessionCopiedMessage": "Study session link copied to clipboard!" + }, + "users": { + "manageRightsFor": "Manage rights for", + "role": "role", + "selectRightsNote": "Select the rights for this role. Note: All users have basic {user} rights by default.", + "userWithQuotes": "\"user\"", + "selectRole": "Select Role", + "manageRights": "Manage Rights", + "rightName": "Right Name", + "description": "Description", + "chooseARole": "Choose a role to assign to the user.", + "roleRightsUpdated": "Role Rights Updated", + "roleRightsUpdatedMessage": "Role rights have been successfully updated", + "userNameLabel": "Username:", + "firstNameLabel": "First Name:", + "lastNameLabel": "Last Name:", + "emailLabel": "Email:", + "updatedAt": "Updated At", + "deletedAt": "Deleted At", + "userUpdated": "User updated", + "userUpdatedMessage": "Successfully updated user!", + "bulkImportUsers": "Bulk Import Users", + "dragAndDropCSV": "Drag and drop CSV file here", + "orClickToUpload": "or click to upload", + "csvTemplateHint": "Please check the format or {0} here.", + "downloadTemplate": "download the template", + "bulkImportConfirm": "Are you sure you want to bulk create {newCount} users {br} and overwrite {dupCount} users?", + "resultSummary": "Successfully created {newCount} users and overwrote {updatedCount} users", + "failedListTitle": "Failed to create the following users:", + "userCannotBeAdded": "User with external Id {extId} cannot be added: {message}", + "uploadToMoodle": "Upload to Moodle", + "downloadResultCsv": "Download Result CSV", + "moodle": "Moodle", + "preview": "Preview", + "result": "Result", + "uploadingCompleted": "Uploading completed", + "uploadingCompletedMessage": "Please go to Moodle to check out your username and password!", + "validationCompleted": "Validation completed", + "validationCompletedMessage": "CSV is valid!", + "pleaseUploadCsv": "Please upload a CSV file", + "viewUserRight": "View User Right", + "userHasNoAssignedRights": "This user has no assigned rights", + "userRole": "User Role", + "userRight": "User Right", + "okay": "okay", + "adminHasFullRights": "admin has full rights", + "roleNoAssociatedRights": "this role does not have associated rights yet", + "csvErrorHint": "Your CSV file contains the following errors. Please fix them and reupload the file.", + "placeholders": { + "provideFirstName": "please provide the first name", + "provideLastName": "please provide the last name", + "provideUsername": "please provide the username - no special characters", + "passwordMinLength": "password should be at least 8 characters long", + "emailExample": "email@example.com" + }, + "passwordLabel": "Password:", + "userCreationCompleted": "User Creation Completed", + "userCreationCompletedMessage": "The user creation was successful" + }, + "submission": { + "assignGroup": { + "title": "Assign Group", + "applyPercentage": "Apply percentage of current selection (randomly chosen):", + "applyButton": "Apply", + "targetCount": "{percentage}% → {target} of {total}", + "stepOne": "Select Submissions", + "stepTwo": "Group Settings", + "stepThree": "Review & Confirm", + "groupNumber": "Group Number", + "groupNumberPlaceholder": "Enter group number", + "additionalSettings": "Additional Settings", + "additionalSettingsPlaceholder": "Enter any additional settings", + "copySubmissions": "Copy Submissions", + "createCopyiesOfSubmissionsLabel": "Create copies of the selected submissions with the specified group number.", + "summaryTitle": "Assignment Summary", + "numberOfSubmissions": "Number of Submissions:", + "groupNumberLabel": "Group Number:", + "additionalSettingsLabel": "Additional Settings:", + "copySubmissionsLabel": "Copy Submissions:", + "reviewNote": "Please review the information above before submitting.", + "successTitle": "Group Assigned", + "successMessage": "Successfully assigned {count} submission(s) to group {group}", + "failureTitle": "Failed to assign group", + "columns": { + "additionalSettings": "Additional Settings" + }, + "filters": { + "noGroupId": "No GroupID" + } + } + }, + "importModal": { + "title": "Import Moodle Submissions", + "stepMoodle": "Moodle", + "stepPreview": "Preview", + "stepConfigure": "Configure", + "stepConfirm": "Confirm", + "stepResult": "Result", + "assignGroup": "Assign Group", + "groupNumber": "Group Number", + "groupNumberPlaceholder": "Enter group number", + "confirmImport": "Confirm Import Settings", + "importSummary": "Import Summary", + "submissionsToImport": "Submissions to import:", + "groupNumberLabel": "Group Number:", + "validationSchema": "Validation schema:", + "noneSelected": "None selected", + "totalSubmissions": "Total submissions:", + "requiredFiles": "Required files:", + "validationDetails": "Validation Details:", + "validationWillCheck": "This will validate ZIP file contents according to the \"{name}\" schema. Submissions must contain all required files: {files}.", + "noValidationSelected": "No validation schema selected. Submissions will be imported without validation.", + "areYouSure": "Are you sure you want to import {count} {message}?", + "submissionSingular": "submission", + "submissionPlural": "submissions", + "successfullyImported": "Successfully imported {count} submissions", + "failedToImport": "Failed to import the following submissions:", + "userCannotBeImported": "User with the User ID {userId} cannot be imported: {message}", + "downloadErrorCSV": "Download Error CSV", + "failedGetSubmissions": "Failed to get student submissions from Moodle", + "failedImportSubmissions": "Failed to import submission from Moodle", + "columns": { + "duplicate": "Duplicate", + "externalId": "External ID", + "userId": "User ID", + "firstName": "First Name", + "lastName": "Last Name", + "fileCount": "File Count" + }, + "filters": { + "new": "New", + "duplicate": "Duplicate" + } + }, + "publishModal": { + "titleReviews": "Publish Reviews", + "titleSubmissions": "Publish Submissions", + "stepDocumentSelection": "Document Selection", + "stepSubmissionSelection": "Submission Selection", + "stepSessionSelection": "Session Selection", + "stepConfirmation": "Confirmation", + "stepPublishingOptions": "Publishing Options", + "textFormat": "Text Format:", + "placeholderSessionLinks": "The placeholder ~SESSION_LINKS~ will be replaced with the review links.", + "placeholderUsername": "The placeholder ~USERNAME~ will be replaced with the CARE username of the document owner.", + "linkCollection": "Link Collection:", + "basedOnStudies": "based on Studies (session links for each study)", + "basedOnSessions": "based on Sessions (links for own sessions)", + "links": "Links:", + "publishMethod": "Publishing Method:", + "downloadCSV": "Download CSV", + "chooseDownloadCSV": "Choose \"Download CSV\" to export the generated feedback text for each recipient.", + "publishReviewLinks": "Publish study session links", + "csvSuccessfullyGenerated": "CSV successfully generated and exported", + "reviewsPublished": "Reviews published", + "reviewLinksPublished": "The review links have been successfully published!", + "failedPublishReviews": "Failed to publish reviews", + "columns": { + "extId": "extId", + "submissionId": "Submission ID", + "group": "Group", + "firstName": "First Name", + "lastName": "Last Name", + "studies": "Studies", + "sessions": "Sessions", + "documentTitle": "Document Title", + "studyName": "Study Name" + } + }, + "uploadModal": { + "title": "Upload Submission", + "stepSelectUser": "Select User", + "stepSelectConfig": "Select Config", + "stepUploadFile": "Upload File", + "assignGroup": "Assign Group", + "groupNumber": "Group Number", + "groupNumberPlaceholder": "Enter group number", + "invalidFiles": "Invalid file(s)", + "pleaseUploadFiles": "Please upload all required files.", + "uploadedFile": "Uploaded file", + "fileSuccessfullyUploaded": "File successfully uploaded!", + "failedUploadFile": "Failed to upload the file", + "columns": { + "id": "ID", + "extId": "extId", + "firstName": "First Name", + "lastName": "Last Name", + "userName": "Username" + } + }, + "systemRoles": { + "regular": "regular", + "maintainer": "maintainer", + "admin": "admin", + "system": "system", + + "descriptions": { + "regular": "no system rights", + "maintainer": "manage users", + "admin": "full control", + "system": "system user" + } + }, + "documents": { + "fields": { + "selectDoc": "Select Document", + "newEmptyDoc": "New Empty Document" + } + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/documents.json b/utils/modules/i18n/en/documents.json new file mode 100644 index 000000000..ec2e7d6b9 --- /dev/null +++ b/utils/modules/i18n/en/documents.json @@ -0,0 +1,69 @@ +{ + "title": "Documents", + "document": "Document", + "documentDefaultName": "document", + "addDocument": "Add document", + "uploadDocument": "Upload document", + "uploadNewDocument": "Upload new document", + "uploadConfiguration": "Upload new configuration file", + "createDocument": "Create document", + "createNewDocument": "Create new document", + "renameDocument": "Rename document...", + "deleteDocument": "Delete document...", + "accessDocument": "Access document...", + "publishDocument": "Publish document...", + "downloadPdfWithAnnotations": "Download PDF with annotations", + "exportDelta": "Export delta to a local file", + "exportHtml": "Export HTML to a local file", + "openStudyCoordinator": "Open study coordinator...", + "importAnnotations": "Import annotations", + "typeOfDocument": "Type of document", + "chooseDocumentType": "Choose document type...", + "nameOfDocument": "Name of the document", + "yesPublish": "Yes, publish it!", + "types": { + "pdf": "PDF", + "html": "HTML", + "modal": "MODAL", + "generalHtml": "General HTML Document", + "studyModal": "Study Modal Document (only usable in studies)" + }, + "messages": { + "deleteConfirm": "Are you sure you want to delete the document?", + "deleteTitle": "Delete Document", + "studyWarning": "There are currently {count} studies running on this document. Deleting it will delete the studies!", + "documentPublished": "Document successfully published!", + "documentAvailableAt": "The document is available under the following link:", + "publishConfirm": "Do you really want to publish the document?", + "cannotBeUndone": "This can not be undone!", + "documentPublishedTitle": "Document published", + "publishedSuccess": "Successfully published document!", + "linkCopiedMessage": "Link copied to clipboard!", + "documentEdited": "The document has been successfully edited.", + "documentEditedTitle": "Document edited", + "documentEditedMessage": "Successfully edited document!", + "configurationUploaded": "Configuration uploaded", + "fileUploaded": "File has been uploaded successfully.", + "annotationsAdded": "{count} annotations were added.", + "annotationImportPartialFailure": "The document was uploaded, but automatic annotation extraction failed. You can still use the document, but some annotations may be missing.", + "issuesOccurred": "Some issues occurred", + "uploadedWithWarnings": "Uploaded with warnings", + "uploadedFile": "Uploaded file", + "documentCreated": "Document created successfully.", + "documentNotFoundTitle": "Document not found", + "documentErrorTitle": "Document Error" + }, + "downloadPdf": { + "title": "Download PDF", + "includeAnnotations": "Include annotations in PDF", + "preparing": "Preparing your PDF...", + "toasts": { + "successTitle": "PDF downloaded successfully", + "successMessage": "Your PDF has been downloaded.", + "successMessageWithAnnotations": "Your PDF with annotations has been downloaded.", + "failedTitle": "Failed to download the PDF", + "unknownError": "Unknown error" + } + } +} + diff --git a/utils/modules/i18n/en/editor.json b/utils/modules/i18n/en/editor.json new file mode 100644 index 000000000..ade3222d8 --- /dev/null +++ b/utils/modules/i18n/en/editor.json @@ -0,0 +1,27 @@ +{ + "reqTitle": "Send a request", + "cmdTitle": "Send a command", + "cmdToSend": "the command to send", + "serviceToContact": "the service to contact", + "waitingForResponse": "Waiting for response", + "payload": "Payload", + "emptyMsgHistory": "No messages sent/received.", + "messages": { + "msgNotReceived": "Received no message from server within 5s." + }, + "seePayload": "See Payload", + "request": "Request", + "copyJsonSuccess": { + "title": "JSON copied", + "message": "JSON copied to clipboard!" + }, + "editJson": "Edit JSON", + "unsavedWarning": { + "unsavedChanges": "Unsaved Changes", + "unsavedChangesMessage": "Are you sure you want to leave? There are unsaved changes, which will be lost." + }, + "history": "History", + "configurator": "Configurator", + "readOnly": "Read-only", + "downloadDocument": "Download document" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/errors.json b/utils/modules/i18n/en/errors.json new file mode 100644 index 000000000..734074700 --- /dev/null +++ b/utils/modules/i18n/en/errors.json @@ -0,0 +1,279 @@ +{ + "auth": { + "invalidResetLink": "Invalid reset link. Please request a new password reset.", + "invalidResetToken": "Invalid reset token. Please request a new password reset.", + "invalidOrExpiredToken": "Invalid or expired reset token.", + "tokenRequired": "Token is required.", + "tokenAndPasswordRequired": "Token and new password are required.", + "failedToValidateToken": "Failed to validate reset token. Please try again.", + "failedToResetPassword": "Failed to reset password. Please try again later.", + "passwordResetFailed": "Password Reset Failed", + "passwordResetDisabled": "Password reset is disabled.", + "passwordResetRateLimited": "Please wait {minutes} minute(s) before requesting another password reset email.", + "emailVerificationError": "Email Verification Error", + "emailVerificationDisabled": "Email verification is disabled.", + "emailAlreadyVerified": "Email address is already verified.", + "verificationRateLimited": "Please wait {minutes} minute(s) before requesting another verification email.", + "failedToVerifyEmail": "Failed to verify email. Please try again later.", + "failedToSendResetEmail": "Failed to send password reset email.", + "failedToSendVerificationEmail": "Failed to send verification email. Please try again later.", + "failedToLogin": "Login failed.", + "failedToCreateUser": "Failed to create user.", + "emailAlreadyTaken": "Email is already in use.", + "usernameTaken": "Username already taken.", + "userNotFoundByEmail": "User with this email does not exist.", + "invalidCredentials": "Invalid User Credentials", + "termsUpdateError": "Consent Update Error", + "consentUpdateError": "Error in updating consent" + }, + "permission": { + "accessError": "Access Error", + "accessDenied": "Access denied.", + "noPermission": "You do not have permission to perform this action.", + "noUploadAccess": "You do not have permission to upload documents.", + "noUserAccess": "You do not have permission to access this user's data.", + "noRoleAccess": "You do not have the required role to perform this action.", + "noAnnotationChangePermission": "You have no permission to change this annotation", + "cannotUpdateOtherUserTable": "You are not allowed to update the table {dataTable} for another user!", + "noDataAccess": "You don't have rights to access this data", + "noPermissionToAccesData": "You don't have permission to access this data", + "noCommentEditPermission": "You are not allowed to edit this comment.", + "noCommentPermission": "You are not allowed to add a comment.", + "noCommentAccess": "You don't have access to this comment", + "noPreprocessSubmissionPermission": "You do not have permission to preprocess submissions" + }, + "configuration": { + "idRequired": "Configuration ID is required.", + "contentRequired": "Configuration content is required.", + "notFound": "Configuration not found." + }, + "validation": { + "fillAllFields": "Please fill in all fields correctly.", + "ensurePasswordRequirements": "Please ensure passwords meet the requirements.", + "validationError": "Validation Error", + "validationFailed": "Validation failed: {message}", + "required": "This field is required", + "requiredFieldMissing": "Required field missing: {fieldKey}", + "fileDownloadFailed": "Failed to download file {fileName}: {message}", + "schemaNotFound": "Validation schema not found: {configurationId}", + "additionalFilesNotAllowed": "Additional files are not allowed. Found: {files}", + "requiredFileMissing": "Required file missing: {file}", + "cannotOpenZip": "Cannot open ZIP file {fileName}: {message}", + "requiredFileMissingInZip": "Required file missing in ZIP {zipFileName}: {file}", + "tooManyMatchesInZip": "Too many matches for {file} in ZIP {zipFileName}: found {found}, max {max}", + "zipReadError": "Error reading ZIP file {fileName}: {message}", + "auth": { + "provideUsername": "Please provide a valid username.", + "providePassword": "Please provide a valid password of at least 8 characters.", + "provideEmail": "Please provide a valid email address.", + "provideFirstName": "Please provide your first name.", + "provideLastName": "Please provide your last name.", + "usernameNoSpecialChars": "Please provide a valid username - no special characters.", + "passwordMinLength": "Password must be at least 8 characters long.", + "acceptTermsRequired": "Please accept the terms.", + "passwordsDoNotMatch": "Passwords do not match." + }, + "documents": { + "selectValidType": "Please select a valid document type.", + "noName": "No name provided", + "enterName": "Please enter a name for the document." + } + }, + "file": { + "noFileUploaded": "No file uploaded", + "invalidFileType": "Invalid file type", + "onlyJsonAllowed": "Only JSON files are allowed.", + "onlyPdfDeltaAllowed": "Only PDF and delta files are allowed.", + "invalidJson": "Invalid JSON format", + "jsonMustBeObject": "The JSON must be an object of key/value pairs.", + "noFileSelected": "No file selected", + "selectJsonFile": "Please select a JSON file to import.", + "noTableAvailable": "No {tableType} available for selection.", + "noParameters": "No file selection parameters found. All parameters are using configuration-based inputs.", + "pdfNotFound": "PDF file not found", + "tableNameRequired": "Table name is required", + "copyJsonError": { + "title": "Json not copied", + "notCopiedMsg": "Could not copy json to clipboard!", + "notLoadedMsg": "Json not loaded or empty, cannot copy." + }, + "pdfLoadingError": { + "title": "PDF Loading Error", + "message": "Error during loading of the PDF file. Make sure the file is not corrupted and in valid PDF format." + } + }, + "clipboard": { + "linkNotCopied": "Link not copied", + "copyFailed": "Could not copy link to clipboard!", + "retrieveFailed": "Failed to retrieve URL. Try again later.", + "configNotCopied": "Config not copied", + "skillConfigCopyFailed": "Could not copy skill configuration to clipboard!", + "couldNotCopyStudySession": "Could not copy study session link to clipboard!" + }, + "documents": { + "deleteFailed": "Document delete failed", + "documentNotPublished": "Document not published", + "documentEditFailed": "Document edit failed", + "failedToUploadConfiguration": "Failed to upload configuration", + "failedToUpload": "Failed to upload", + "failedToProcessPdf": "Failed to process PDF", + "errorProcessingPdf": "Error processing PDF", + "failedToLoadDocContent": "Failed to load the document content.", + "documentOpenError": "Document Open Error", + "documentCloseError": "Document Close Error", + "documentError": "Document Error", + "uploadingFailed": "Uploading failed", + "noDocumentSelected": "You need to select a document.", + "notFound": "Document not found.", + "unsupportedDocumentTypeOperation": "This operation is only supported for HTML/MODAL documents.", + "processingError": "Error processing document {documentId}: {message}", + "fileNotFound": "File not found for document {documentId}: {filePath}", + "readError": "Error reading document file {documentId}: {message}", + "notEnoughDocumentsForRole": "Not enough documents to review for role {roleName}. Please add more documents.", + "notEnoughDocumentsForReviewer": "Not enough documents to review for {reviewerName}. Please add more documents." + }, + "editor": { + "cursorPositionError": { + "title": "No Cursor Position", + "message": "Please click in the editor to set the cursor position before inserting a placeholder." + }, + "previousEditFailed": "Previous edit failed; try again", + "editHistoryRetrievalFailed": "Failed retrieving edit history" + }, + "studies": { + "studyCannotStart": "Study cannot be started!", + "studyClosingFailed": "Study closing failed", + "studyDeleteFailed": "Study delete failed", + "studyRestartFailed": "Study restart failed", + "templateSaveFailed": "Template Save Failed", + "templateCreationFailed": "Template Creation Failed", + "sessionNotFinished": "Session Not Finished", + "stepUpdateFailed": "Step Update Failed", + "studyClosed": "This study is closed", + "studyEnded": "This study has ended", + "studyNotFound": "Study not found", + "studyNotStarted": "This study has not started yet", + "sessionLimitExceeded": "Cannot create more than {limit} sessions for this study.", + "sessionLimitPerUserExceeded": "Cannot create more than {limit} sessions for this user.", + "missingContextOrStepDocuments": "Missing context or step documents in options. Cancelling transaction.", + "studyStep": { + "notFound": "No first step found for this study", + "referencedStepNotFound": "Referenced study step not found for workflow step {originalEntryId}", + "referencedDocumentNotFound": "Referenced document not found for study step {referencedStudyStepId}", + "documentNotFound": "Document not found: document ID {dataDocumentId} is missing for step {dataWorkflowStepId}", + "documentTypeMismatch": "Document type mismatch: step {dataWorkflowStepId} expects an Editor document (type 1), but found type {documentType}." + } + }, + "settings": { + "errorLoading": "Error Loading Settings", + "errorSaving": "Error Saving Settings", + "failedToImport": "Failed to import settings", + "noAccessPermission": "You do not have permission to access settings.", + "noSavePermission": "You do not have permission to save settings." + }, + "users": { + "errorFetchingUsers": "Error fetching users", + "userNotDeleted": "User not deleted", + "updateFailed": "Failed to update", + "failedToGetUsersFromMoodle": "Failed to get users from Moodle", + "failedToBulkCreateUsers": "Failed to bulk create users", + "failedToCheckDuplicateUsers": "Failed to check duplicate users", + "failedToCheckDuplicateUsersMessage": "Please contact CARE staff to resolve the issue", + "errorFetchingUserRights": "Error fetching user rights", + "userCreationFailed": "User Creation Failed", + "userNotFound": "User not found", + "failedToUpdateUser": "Failed to update user: User not found", + "noUserFoundForRole": "No users found for role {roleName}. Please add users to the role." + }, + "submission": { + "notFound": "Submission with id {submissionId} not found", + "documentCopyFailed": "Failed to copy document with id {documentId}: {message}", + "noValidFiles": "No valid files found for submission {submissionId}", + "missingAdminRights": "Cannot cancel preprocessing: missing admin rights", + "noActivePreprocessing": "Cannot cancel preprocessing: no active preprocessing", + "invalidPreprocessRequest": "Invalid preprocessing request payload.", + "noSkillParameterMappings": "No skill parameter mappings provided.", + "copyFailed": "Failed to copy submission {submissionId}. Error: {originalMessage}" + }, + "tags": { + "tagSetDeleteFailed": "TagSet delete failed", + "tagSetPublishFailed": "TagSet publishing failed", + "tagSetEmpty": "Tag set is empty", + "tagSetEmptyMessage": "You can not select an empty tag set as default.", + "tagUpdateFailed": "Tag Update Failed", + "emptyTagset": { + "title": "Empty Tagset", + "message": "No tagset or an empty tagset have been selected. Cannot make annotations." + } + + }, + "annotator": { + "commentNotUpdated": "Comment not updated", + "annotationUpdateFailed": "Annotation Update Failed", + "annotationNotRetrieved": "Annotation not retrieved", + "commentsNotRetrieved": "Comments not retrieved" + }, + "nlp": { + "timeout": "Timeout in request for skill {skill} - Request failed!", + "invalidService": "The provided service is invalid. Please consult with the service provider.", + "configCopyFailed": "Configuration not loaded or empty, cannot copy.", + "downloadFailed": "Download failed", + "configDownloadFailed": "Failed to download skill config, as it is not loaded", + "msgNotReceived": "Received no message from server within 5s." + }, + "server": { + "unexpectedError": "An unexpected error occurred. Please try again.", + "unknownError": "Unknown error" + }, + "page": { + "notFoundTitle": "404 not found", + "notFoundMessage": "The page you are looking for does not exist." + }, + "download": { + "abortedTitle": "Download aborted", + "serverTimeout": "The server did not respond. Please try again later.", + "inProgress": "Another download is in progress. Please wait.", + "exportAbortedTitle": "Export aborted", + "exportFailedTitle": "Export Failed", + "exportFailedMessage": "Export failed for {id}." + }, + "element": { + "invalidInput": "The input is invalid.", + "fieldRequired": "This field is required." + }, + "collaboration": { + "collabUpdateFailed": "Collaboration Update Failed", + "collabCreationFailed": "Could not start collaboration" + }, + "connectionError": "Connection error! Reconnecting...", + "roles": { + "loadAvailableRightsFailed": "Failed to load available rights", + "loadRoleRightsFailed": "Failed to load role rights", + "assignRoleRightsFailed": "Failed to assign role rights" + }, + "csv": { + "missingRequiredHeaders": "CSV does not contain all required headers", + "emptyValue": "Empty value found for {key} at index {index}", + "duplicateId": "Duplicate id found: {extId} at index {index}", + "duplicateEmail": "Duplicate email found: {email} at index {index}", + "rolesNotCommaSeparated": "Roles not comma-separated for id {id} at index {index}", + "invalidEmailFormat": "Invalid email format for id {id} at index {index}: {email}", + "parseError": "Error parsing file: {message}" + }, + "rpc": { + "serviceNotConnected": "RPC service not connected", + "requestFailed": "RPC request {eventName} failed: {message}", + "downloadFailed": "Failed to download submissions: {message}", + "annotationExtractionFailed": "Failed to extract annotations: {message}", + "annotationEmbeddingFailed": "Failed to embed annotations: {message}", + "annotationDeletionFailed": "Failed to delete annotations: {message}" + }, + "database": { + "failedToUpdateData": "Failed to update data" + }, + "assignment": { + "unableToAssignEnoughDocuments": "Unable to assign enough documents for {reviewerName} in role {roleName}", + "couldNotAssignReviewers": "Could not assign all reviewers. Please try again.", + "invalidMode": "Invalid mode provided for assignment creation." + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/index.js b/utils/modules/i18n/en/index.js new file mode 100644 index 000000000..5a5015313 --- /dev/null +++ b/utils/modules/i18n/en/index.js @@ -0,0 +1,53 @@ +import common from './common.json' +import auth from './auth.json' +import errors from './errors.json' +import dashboard from './dashboard.json' +import documents from './documents.json' +import users from './users.json' +import studies from './studies.json' +import annotator from './annotator.json' +import settings from './settings.json' +import tags from './tags.json' +import modals from './modals.json' +import nlp from './nlp.json' +import navigation from './navigation.json' +import assessment from './assessment.json' +import editor from './editor.json' +import tagSelector from './tagSelector.json' +import infoPanel from './infoPanel.json' +import report from './report.json' +import review from './review.json' +import basic from './basic.json' +import coordinator from './coordinator.json' +import moodle from './moodle.json' +import submission from './submission.json' +import sidebar from './sidebar.json' +import components from './components.json' + +export default { + common, + auth, + errors, + dashboard, + documents, + users, + studies, + annotator, + settings, + tags, + modals, + nlp, + navigation, + assessment, + editor, + tagSelector, + infoPanel, + report, + review, + basic, + coordinator, + moodle, + submission, + sidebar, + components, +} diff --git a/utils/modules/i18n/en/infoPanel.json b/utils/modules/i18n/en/infoPanel.json new file mode 100644 index 000000000..ee95db21b --- /dev/null +++ b/utils/modules/i18n/en/infoPanel.json @@ -0,0 +1,6 @@ +{ + "description": "Description:", + "maxPoints": "Maximum Points:", + "pointsAbbreviation": "P", + "scoringCriteria": "Scoring Criteria:" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/modals.json b/utils/modules/i18n/en/modals.json new file mode 100644 index 000000000..a0eb00486 --- /dev/null +++ b/utils/modules/i18n/en/modals.json @@ -0,0 +1,44 @@ +{ + "confirm": "Confirm", + "confirmAction": "Confirm {action}", + "pleaseConfirm": "Please confirm", + "sending": "Sending...", + "sendResetEmail": "Send Reset Email", + "passwordReset": "Password Reset", + "passwordUpdated": "Password Updated", + "passwordResetSuccess": "Password has been reset successfully.", + "loading": "Loading...", + "closeModal": "Close", + "placeholders": { + "documentPreview": "Document Preview", + "placeholderLegend": "Placeholder Legend", + "configurePlaceholders": "Configure Placeholders", + "firstDataSource": "First Data Source:", + "secondDataSource": "Second Data Source:", + "dataSource": "Data Source:", + "selectFirstDataSource": "Select first data source...", + "selectSecondDataSource": "Select second data source...", + "selectDataSource": "Select data source...", + "noPlaceholders": "No placeholders found in the document.", + "documentError": "Document Error", + "invalidDocumentContent": "The document content is invalid or empty. Please try again.", + "failedToFetchDocument": "Failed to fetch the document.", + "addInformation": "Add here the information for the placeholder:", + "dataMissingOrInvalid": "~ Placeholder data missing or invalid ~", + "dataMissing": "~ Placeholder data missing ~", + "firstVersionStep": "First Version (Step {step})", + "currentVersionStep": "Current Version (Step {step})" + }, + "modal": "Modal", + "noContentForThisStep": "No content available for this step.", + "finishStudy": "Finish Study", + "exportStudyData": "Export Study Data", + "returnToStudies": "'Return to Studies'", + "revisions": { + "revision": "Revision", + "revisionOne": "Revision 1", + "revisionTwo": "Revision 2" + }, + "chart": "Chart", + "comparisonChart": "Comparison Chart" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/moodle.json b/utils/modules/i18n/en/moodle.json new file mode 100644 index 000000000..94a360a21 --- /dev/null +++ b/utils/modules/i18n/en/moodle.json @@ -0,0 +1,14 @@ +{ + "assignmentId": "Assignment ID:", + "courseId": "Course ID:", + "apiKey": "Moodle API Key:", + "apiUrl": "Moodle URL:", + "refresh": "Refresh", + "refreshTooltip": "Refresh assignments list", + "placeholders": { + "assignmentId": "Enter Assignment ID", + "courseId": "Enter Course ID", + "apiKey": "Enter API Key", + "apiUrl": "https://example.moodle.com" + } + } \ No newline at end of file diff --git a/utils/modules/i18n/en/navigation.json b/utils/modules/i18n/en/navigation.json new file mode 100644 index 000000000..82d4df48a --- /dev/null +++ b/utils/modules/i18n/en/navigation.json @@ -0,0 +1,16 @@ +{ + "goBack": "Go back...", + "project": "Project: {name}", + "documentation": "Documentation", + "feedback": "Feedback", + "projectPage": "Project Page", + "sidebar": { + "collapseSidebar": "Collapse sidebar", + "toggleSidebar": "Toggle sidebar", + "hideSidebar": "Hide sidebar", + "showSidebar": "Show sidebar", + "moreActions": "More actions", + "noContent": "No sidebar content selected.", + "sidebarSection": "Sidebar section" + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/nlp.json b/utils/modules/i18n/en/nlp.json new file mode 100644 index 000000000..d66b3410b --- /dev/null +++ b/utils/modules/i18n/en/nlp.json @@ -0,0 +1,126 @@ +{ + "service": "NLP Service", + "serviceRequest": "NLP Service Request", + "notAvailable": "{name} not available", + "skillDetails": "Skill Details", + "copyConfig": "Copy config", + "downloadConfig": "Download config", + "sendCommand": "Send command", + "configCopied": "Config copied", + "skillConfigCopied": "Skill configuration copied to clipboard!", + "downloadSuccess": "Download success", + "downloadedConfigMessage": "Downloaded {name} configuration", + "services": { + "availableServices": "Available Services", + "noServices": "No services configuration available for this step." + }, + "inputConfirm": { + "confirmSelections": "Confirm Your Selections", + "selectedSkill": "Selected Skill:", + "inputMappings": "Input Mappings:", + "selectedFiles": "Selected Files:", + "baseFileSelections": "Base File Selections:", + "defaultConfiguration": "Configuration", + "unknownSelection": "Unknown" + }, + "inputFiles": { + "filesSelectedFor": "Files selected for {param}: {count} file(s)", + "selectFilesFor": "Please select files for parameter: {param}", + "documents": "Documents", + "submissions": "Submissions", + "noGroupId": "No GroupID" + }, + "inputGroup": { + "validationConfiguration": "Validation Configuration {id}" + }, + "skillSelector": { + "selectNlpSkill": "Select NLP Skill:" + }, + "inputMap": { + "inputMapping": "Input Mapping", + "outputMapping": "Output Mapping", + "saveInDocumentData": "Save in Document Data", + "insertIntoEditor": "Insert into Editor" + }, + "request": { + "title": "NLP Service Request", + "timeout": "Timeout in request for skill: {skill}" + }, + "preprocessing": { + "title": "Preprocess Grading", + "cancelButton": "Cancel Preprocess", + "submissionName": "Submission {id}", + "cancelApplySkills": "Cancel Apply Skills", + "cancelSuccess": "Preprocessing cancelled successfully.", + "toasts": { + "inProgressTitle": "Preprocessing In Progress", + "inProgressMsg": "Preprocessing is currently running. Showing progress...", + "cancelledTitle": "Preprocessing Cancelled", + "cancelledMsg": "Preprocessing has been cancelled.", + "cancellationFailedTitle": "Preprocessing Cancellation Failed", + "startedTitle": "Preprocessing Started", + "startedMsg": "Preprocessing has been initiated.", + "nowRunningMsg": "Preprocessing is now running. Progress shown in the modal." + }, + "setupStepper": { + "title": "Apply Skills", + "submitButton": "Apply Skills", + "steps": { + "selectSkill": "Select Skill", + "selectFiles": "Select Files", + "selectBaseFiles": "Select Base Files", + "confirmation": "Confirmation" + }, + "closeModalTitle": "Close Modal", + "closeModalMessage": "Current selections will be lost if you close this modal. Are you sure you want to continue?" + }, + "processStepper": { + "steps": { + "progress": "Processing Progress", + "confirmCancel": "Confirm Cancellation" + }, + "stats": { + "processed": "Processed:", + "currentRuntime": "Current request running time:", + "estimatedPerRequest": "Estimated time per request:", + "estimatedRemaining": "Estimated time remaining:", + "calculating": "Calculating...", + "almostDone": "Almost done..." + }, + "queue": { + "title": "Submissions in Queue", + "empty": "No submissions in queue. Processing the last request...", + "columns": { + "id": "ID", + "submissionName": "Submission Name", + "user": "User" + } + }, + "cancel": { + "title": "Cancel Processing", + "message": "Are you sure you want to cancel the remaining requests?", + "confirmButton": "Confirm", + "nextButton": "Next" + } + } + }, + "skills": { + "title": "Skills", + "status": { + "online": "ONLINE", + "offline": "OFFLINE", + "activating": "Activating" + }, + "columns": { + "nodes": "# Nodes", + "activated": "Activated", + "fallback": "Fallback" + }, + "toasts": { + "settingUpdatedTitle": "Setting Updated", + "settingUpdatedMessage": "Skill \"{name}\" activation updated.", + "updateFailedTitle": "Failed to Update Setting" + } + } + +} \ No newline at end of file diff --git a/utils/modules/i18n/en/report.json b/utils/modules/i18n/en/report.json new file mode 100644 index 000000000..5f6f172f8 --- /dev/null +++ b/utils/modules/i18n/en/report.json @@ -0,0 +1,10 @@ +{ + "noText": "(no text)", + "ref": "(ref. {citation})", + "show": "(show)", + "reviewReport": "Review Report", + "emptyReport": "Empty report -- no annotations or comments found.", + "generalComments": "General Comments", + "noComments": "No comments.", + "tip": "*Tip: Hover over a reference to see the referenced text or click to view the annotation in the PDF." +} \ No newline at end of file diff --git a/utils/modules/i18n/en/review.json b/utils/modules/i18n/en/review.json new file mode 100644 index 000000000..8ba41a97f --- /dev/null +++ b/utils/modules/i18n/en/review.json @@ -0,0 +1,9 @@ +{ + "evaluateSession": "Evaluate this session", + "sessionNotFinishedYet": "This session is not finished yet, please wait until the session is closed!", + "thankYouForEvaluating": "Thank you for evaluating this session!", + "sessionAlreadyEvaluated": "This session is already evaluated.", + "makeDecision": "Make a decision based on this study session.", + "comment": "Comment", + "acceptance": "Acceptance" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/settings.json b/utils/modules/i18n/en/settings.json new file mode 100644 index 000000000..78893291f --- /dev/null +++ b/utils/modules/i18n/en/settings.json @@ -0,0 +1,19 @@ +{ + "title": "Settings", + "changeUserSettings": "Change User Settings", + "exportJson": "Export JSON", + "importJson": "Import JSON", + "saveSettings": "Save Settings", + "saveSettingsUnsaved": "Save Settings (Unsaved changes)", + "importSettings": "Import Settings", + "rememberToSave": "Remember to click Save Settings after making changes.", + "importDescription": "Select a previous downloaded settings file. Only existing keys will be updated.", + "messages": { + "settingsLoaded": "Settings Loaded", + "settingsLoadedMessage": "Settings have been successfully loaded.", + "settingsSavedSuccessfully": "Settings saved successfully.", + "settingsImported": "Settings imported", + "updatedSettings": "Updated {count} existing setting(s).", + "unsavedChangesWarning": "You have unsaved changes in your settings. Are you sure you want to leave without saving?" + } +} diff --git a/utils/modules/i18n/en/sidebar.json b/utils/modules/i18n/en/sidebar.json new file mode 100644 index 000000000..ffd2a5bf3 --- /dev/null +++ b/utils/modules/i18n/en/sidebar.json @@ -0,0 +1,41 @@ +{ + "placeholders": "Placeholders", + "textPlaceholder": "Text placeholder", + "textPlaceholderDescription": "Add text content blocks", + "singleChart": "Single chart", + "singleChartDescription": "Visualize data with a chart", + "comparisonChart": "Comparison Chart", + "comparisonChartDescription": "Compare multiple data sets", + "currentVersion": "Current Version", + "versionHistory": "Version History", + "anonymousUser": "Anonymous User", + "periode": { + "today": "Today", + "yesterday": "Yesterday", + "thisWeek": "This week", + "lastWeek": "Last week", + "thisMonth": "This month", + "lastMonth": "Last month", + "older": "Older" + }, + "nav": { + "home": "Home", + "documents": "Documents", + "tags": "Tags", + "settings": "Settings", + "logs": "Logs", + "studies": "Studies", + "study_sessions": "Study Sessions", + "users": "Users", + "nlp_skills": "NLP Skills", + "user_stats": "User Statistics", + "projects": "Projects", + "submissions": "Submissions", + "review_documents": "Review Documents", + "configurations": "Configurations", + "groups": { + "default": "Default", + "admin": "Admin" + } + } +} \ No newline at end of file diff --git a/utils/modules/i18n/en/studies.json b/utils/modules/i18n/en/studies.json new file mode 100644 index 000000000..ff4456e94 --- /dev/null +++ b/utils/modules/i18n/en/studies.json @@ -0,0 +1,241 @@ +{ + "title": "Studies", + "study": "Study", + "template": "Template", + "sessions": "Sessions", + "savedTemplates": "Saved Templates", + "closeAllStudies": "Close All Studies", + "addBulkAssignments": "Add Bulk Assignments", + "addSingleAssignment": "Add Single Assignment", + "editStudy": "Edit study", + "deleteStudy": "Delete study", + "openStudy": "Open study", + "restartStudy": "Restart study", + "closeStudy": "Close study", + "copyLink": "Copy link to study", + "inspectSessions": "Inspect sessions", + "saveAsTemplate": "Save as Template", + "showInformation": "Show information", + "finishStudy": "Finish Study", + "finishStudyAgain": "Finish Study Again", + "returnToDashboard": "Return to dashboard", + "backToDashboard": "Back to Dashboard", + "openSessions": "Open Sessions", + "openSessionsForStudy": "Open sessions for {name}", + "resumeSession": "Resume session", + "startSession": "Start session", + "joinStudy": "Join study", + "startStudy": "Start study", + "finishSession": "Finish session", + "sessionNotStarted": "Session has not started yet", + "timeLeft": "Time Left", + "notStartedYet": "The study has not started yet!", + "noMoreSessions": "No more sessions available for this study.", + "clickToStart": "Click \"Start User Study\" to start the user study.", + "collaborativeNote": "This is a collaborative user study, so everyone can join and proceed with this study simultaneously!", + "thankYouParticipation": "Thank you for your participation :-)", + "canCloseBrowser": "You can close the browser now!", + "thankYouJoining": "Thank you for joining!", + "clickFinishToSubmit": "With a click on the finish button, you can submit your results.", + "timeExpired": "The time has expired, no more changes are possible.", + "nameOfStudy": "Name of the study:", + "columns": { + "status": "Status", + "created": "Created", + "sessions": "Sessions", + "started": "Started", + "finished": "Finished", + "sessionLimit": "Session Limit", + "sessionLimitPerUser": "Session Limit per User", + "resumable": "Resumable", + "collaborative": "Collaborative", + "multipleSubmissions": "Multiple Submissions", + "timeLimit": "Time Limit" + }, + "status": { + "notStarted": "Not started", + "running": "Running", + "closed": "Closed", + "ended": "Ended" + }, + "messages": { + "studyStarted": "Study started", + "enjoy": "Enjoy!", + "studyPublishedSuccess": "Study published successfully!", + "participantsCanJoin": "Participants can join using the following link:", + "studyClosed": "Study closed", + "studyClosedMessage": "The study has been closed", + "studyDeleted": "Study deleted", + "studyDeletedMessage": "The study has been deleted", + "studyRestarted": "Study restarted", + "studyRestartedMessage": "The study has been restarted", + "linkCopied": "Link copied", + "linkCopiedMessage": "Study link copied to clipboard!", + "templateCreatedSuccess": "Template created successfully!", + "templateCreated": "Template Created", + "templateCreatedMessage": "The template has been created.", + "templateSaved": "Template Saved", + "templateSavedMessage": "This study has been saved as a template.", + "deleteConfirm": "Are you sure you want to delete the study?", + "deleteTitle": "Delete Study", + "saveAsTemplateConfirm": "Are you sure you want to save this study as a template?", + "saveAsTemplateTitle": "Save Study as Template", + "studyFinished": "This study has finished on {date}", + "studyStartDate": "Start: {date}", + "timeLimitNote": "Please note that there is a time limitation of {minutes} min for this study!", + "sessionsLeft": "You have {count} sessions left for this study.", + "sessionWarning": "There are currently {count} study sessions existing for this study. Deleting it will delete the study sessions!", + "sessionFinished": "Session Finished", + "sessionFinishedMessage": "Your session has been submitted successfully.", + "studySessionErrorTitle": "Study Session Error" + }, + "loading": { + "title": "Loading Study Step", + "nlpError": "An error occurred while processing NLP results. Please try again or skip NLP support.", + "generalError": "An error occurred while loading the study step. Please try again later.", + "buttons": { + "tryAgain": "Try Again", + "skip": "Skip NLP Support" + }, + "messages": [ + "Thinking through your request...", + "Almost there, just refining the details...", + "Gathering the best possible answer...", + "Just a few more moments, precision takes time...", + "Working on something smart for you...", + "One moment... I'm thinking faster than it looks...", + "Just aligning a few neurons...", + "Spinning up some linguistic magic...", + "Your request is traveling through a billion neurons...", + "Looking around corners for edge cases...", + "Running a quick plausibility pass...", + "Consulting the wisdom of the crowd...", + "Almost ready..." + ] + }, + "dashboard": { + "activeSessions": { + "title": "Active Study Sessions", + "noSessions": "You have no active study sessions. Enter a study by clicking on the study link or create your own study." + }, + "closedSessions": { + "title": "Closed Study Sessions", + "noSessions": "You have no closed study sessions." + }, + "studyTitle": "Study: {name}", + "studyTitleWithAuthor": "Study: {name} (from {author})", + "noName": "", + "noDueDate": "no due date" + }, + "modalTitle": { + "createTemplate": "Create Template", + "editTemplate": "Edit Template", + "newTemplate": "New Template", + "createStudy": "Create Study", + "editStudy": "Edit Study", + "newStudy": "New Study" + }, + "unit": { + "sessions": "Session(s)" + }, + "form": { + "name": { + "label": "Name of the study", + "placeholder": "My user study" + }, + "workflow": { + "label": "Select workflow for study", + "help": "Choose a workflow template for the study steps." + }, + + "tagSet": { + "label": "Tag set for the study", + "help": "Select a tag set to use in the study." + }, + "stepDocuments": { + "label": "Assign documents to workflow steps" + }, + "description": { + "label": "Description of the study", + "help": "This text will be displayed at the beginning of the user study." + }, + "timeLimit": { + "label": "How much time does a participant have for the study?", + "help": "Set the maximum time allowed. Use 0 to disable the time limit." + }, + "limitSessions": { + "label": "Limit the number of sessions for the study", + "help": "Set how many times participants can start or resume the study. Use 0 for unlimited sessions." + }, + "limitSessionsPerUser": { + "label": "Limit the number of sessions per user", + "help": "Set how many times each participant can start or resume the study. Use 0 for unlimited sessions." + }, + "collab": { + "label": "Should the study be collaborative?" + }, + "anonymize": { + "label": "Should the comments be anonymized?" + }, + "resumable": { + "label": "Should the study be resumable?" + }, + "multipleSubmit": { + "label": "Allow multiple submissions?", + "help": "Specify whether participants can submit the study more than once." + }, + "start": { + "label": "Study sessions cannot start before" + }, + "end": { + "label": "Study sessions cannot start after" + } + }, + "workflowConfig": { + "addLinkEod": { + "reviewLink": { + "help": "The link is appended to the end of the document. `~SESSION_HASH~` is replaced with the current session hash." + }, + "reviewText": { + "help": "Do you find the feedback helpful?" + } + }, + "assessment": { + "configurationId": { + "label": "Assessment Configuration File:", + "help": "Select the configuration file for this workflow step assessment." + }, + "forcedAssessment": { + "label": "Forced Assessment", + "help": "If enabled, reviewers must save a score and justification for every criterion before they can proceed." + } + }, + "assessmentWithAi": { + "configurationId": { + "label": "Configuration File:", + "help": "Select the configuration file for this workflow step." + }, + "forcedAssessment": { + "label": "Forced Assessment", + "help": "If enabled, reviewers must save a score and justification for every criterion before they can proceed." + } + }, + "modalSize": { + "label": "Modal Size", + "options": { + "small": "Small", + "medium": "Medium", + "large": "Large", + "extraLarge": "Extra Large" + } + } + }, + "workflow": { + "peer_review_workflow": "Peer Review Workflow", + "peer_review_workflow_(assessment)": "Peer Review Workflow (Assessment)", + "peer_review_workflow_(assessment_with_ai)": "Peer Review Workflow (Assessment with AI)", + "ruhr-uni_bochum_project": "Ruhr-Uni Bochum Project", + "ruhr-uni_bochum_project_control": "Ruhr-Uni Bochum Project (Control)", + "annotation_workflow": "Annotation Workflow" + } +} diff --git a/utils/modules/i18n/en/submission.json b/utils/modules/i18n/en/submission.json new file mode 100644 index 000000000..ec60b0318 --- /dev/null +++ b/utils/modules/i18n/en/submission.json @@ -0,0 +1,56 @@ +{ + "dashboard": { + "title": "Submissions", + "buttons": { + "assignGroup": "Assign Group", + "publishReviews": "Publish Reviews", + "publishSubmissions": "Publish Submissions", + "manualImport": "Manual Import", + "importMoodle": "Import via Moodle", + "viewProcessing": "View Processing", + "applySkills": "Apply Skills" + }, + "tooltips": { + "assignGroup": "Assign Group", + "publishReviews": "Publish Reviews", + "publishSubmissions": "Publish Submissions", + "manualImport": "Manual Import", + "importMoodle": "Import via Moodle", + "viewProcessing": "View Processing Progress", + "applySkills": "Apply Skills", + "processingActive": "Processing active" + }, + "columns": { + "id": "ID", + "firstName": "First Name", + "lastName": "Last Name", + "submissionId": "Submission ID", + "group": "Group", + "validationId": "Validation ID", + "createdAt": "Created At" + }, + "actions": { + "download": "Download submission files", + "delete": "Delete document..." + }, + "delete": { + "title": "Delete Document", + "message": "Are you sure you want to delete the document?", + "warning": "There is currently {count} study running on this document. Deleting it will delete the study! | There are currently {count} studies running on this document. Deleting it will delete the studies!" + }, + "toasts": { + "deleteSuccessTitle": "Document deleted", + "deleteSuccessMessage": "The document has been deleted", + "deleteFailedTitle": "Failed to delete document", + "noDocumentsTitle": "No documents found", + "noDocumentsMessage": "This submission has no associated documents to download", + "downloadIssueTitle": "Document download issue", + "downloadIssueMessage": "Could not download {name}", + "downloadErrorTitle": "Download error", + "downloadErrorMessage": "Failed to download {name}: {error}", + "downloadCompleteTitle": "Download complete", + "downloadCompleteMessage": "Downloaded submission {id} with {count} documents", + "downloadFailedTitle": "Download failed" + } + } + } \ No newline at end of file diff --git a/utils/modules/i18n/en/tagSelector.json b/utils/modules/i18n/en/tagSelector.json new file mode 100644 index 000000000..310104b8b --- /dev/null +++ b/utils/modules/i18n/en/tagSelector.json @@ -0,0 +1,6 @@ +{ + "chooseTag": "Choose a tag...", + "selectTag": "Please select a valid tag.", + "addTag": "Add tag...", + "noTags": "No Tags" +} \ No newline at end of file diff --git a/utils/modules/i18n/en/tags.json b/utils/modules/i18n/en/tags.json new file mode 100644 index 000000000..051c754e6 --- /dev/null +++ b/utils/modules/i18n/en/tags.json @@ -0,0 +1,74 @@ +{ + "title": "Tag Sets", + "tagSet": "Tag Set", + "addNewTagSet": "Add new tag set", + "copyTagSet": "Copy tag set", + "editTagSet": "Edit tag set", + "deleteTagSet": "Delete tag set", + "shareTagSet": "Share tag set", + "selectAsDefault": "Select tag set as default", + "modalTitle": { + "newTagSet": "New Tag Set", + "editTagSet": "Edit Tag Set" + }, + "columns": { + "tags": "Tags", + "lastChange": "Last Change", + "user": "User" + }, + "messages": { + "deleteTitle": "Delete Tagset", + "deleteConfirm": "Do you really want to delete the Tagset?", + "tagSetDeleted": "TagSet deleted", + "tagSetDeletedMessage": "The TagSet was successfully deleted", + "publishTitle": "Publish Tagset", + "publishConfirm": "Do you really want to publish the tagset? Note: Once you published it, you can't unpublish the tagset!", + "tagSetPublished": "TagSet published", + "tagSetPublishedMessage": "The TagSet was successfully published" + }, + "form": { + "name": { + "label": "Name of the Tag set:", + "placeholder": "My tag set" + }, + "description": { + "label": "Description of the Tag set:", + "placeholder": "Tag set description" + }, + "tags": { + "label": "Tags:" + } + }, + "editMainTag": "Edit main tag", + "basicTags": { + "highlight": "Highlight", + "strength": "Strength", + "weakness": "Weakness", + "other": "Other" + }, + "basicTagGroups": { + "peerReview": "Peer Review", + "standardSet": "A standard tagset for peer review process" + }, + "tag":{ + "form": { + "name":{ + "label": "Name", + "placeholder": "Name of the Tag" + }, + "description": { + "label": "Description", + "placeholder":"Tag description" + }, + "colorCode": { + "label": "Color", + "options": { + "info": "Info", + "warning": "Warning", + "success": "Success", + "danger": "Danger" + } + } + } + } +} diff --git a/utils/modules/i18n/en/users.json b/utils/modules/i18n/en/users.json new file mode 100644 index 000000000..f8e8a38b1 --- /dev/null +++ b/utils/modules/i18n/en/users.json @@ -0,0 +1,83 @@ +{ + "title": "Users", + "downloadUsers": "Download Users", + "assignRoles": "Assign Roles", + "uploadPassword": "Upload Password", + "importCsv": "Import CSV", + "importViaMoodle": "Import via Moodle", + "addUser": "Add User", + "editUser": "Edit User", + "viewRights": "View Rights", + "resetPassword": "Reset Password", + "deleteUser": "Delete User", + "columns": { + "firstName": "First Name", + "lastName": "Last Name", + "userName": "User", + "email": "Email", + "acceptTerms": "Accept Terms", + "acceptStats": "Accept Stats", + "acceptDataSharing": "Accept Data Sharing", + "verified": "Verified", + "lastLogin": "Last Login" + }, + "messages": { + "deleteConfirm": "Are you sure you want to delete this user?", + "deleteTitle": "Delete User", + "userDeleted": "User deleted", + "userDeletedMessage": "User has been deleted" + }, + "stats": { + "exportCsv": "Export as CSV", + "exportJson": "Export as JSON", + "userStatsTitle": "Stats for {count} User | Stats for {count} Users", + "columns": { + "user": "User", + "id": "ID", + "lastLogin": "Last Login", + "time": "Time", + "action": "Action", + "data": "Data" + }, + "toasts": { + "exportFailedTitle": "Export Failed", + "exportFailedMessage": "Export failed." + } + }, + "roles": { + "teacher": "teacher", + "mentor": "mentor", + "student": "student", + "guest": "guest", + "user": "user", + "admin": "admin" + }, + "rightDescriptions": { + "backend_socket_user_getUsers_student": "Access to get all students", + "backend_socket_user_getUsers_mentor": "Access to get all mentors", + "frontend_dashboard_users_view": "Access to view users in the dashboard", + "backend_socket_user_getUsers_all": "Access to get all users", + "frontend_dashboard_studies_addBulkAssignments": "Access to bulk add assignments in the dashboard", + "frontend_dashboard_studies_addSingleAssignments": "Access to add assignments in the dashboard", + "frontend_dashboard_studies_fullAccess": "Access to view open studies and sessions", + "frontend_dashboard_studies_view_readOnly": "Access to open sessions in read-only mode", + "frontend_dashboard_studies_view_userPrivateInfo": "Access to view private user information such as first and last name", + "frontend_dashboard_home_view": "Access to view home in the dashboard", + "frontend_dashboard_documents_view": "Access to view documents in the dashboard", + "frontend_dashboard_tags_view": "Access to view tag sets in the dashboard", + "frontend_dashboard_projects_view": "Access to view projects in the dashboard", + "frontend_dashboard_studies_view": "Access to view studies in the dashboard", + "frontend_dashboard_study_sessions_view": "Access to view study sessions in the dashboard", + "study_template_delete": "Access to delete templates" + }, + "roleDescriptions": { + "admin": "Full control", + "user": "No system rights", + "teacher": "Responsible for coordination", + "mentor": "Has the right to grade", + "student": "Leaves inline commentary", + "guest": "Has limited rights when using the platform", + "system": "System user" + } +} + diff --git a/utils/modules/i18n/index.js b/utils/modules/i18n/index.js new file mode 100644 index 000000000..892622207 --- /dev/null +++ b/utils/modules/i18n/index.js @@ -0,0 +1,72 @@ +/** + * Shared i18n module + * + * Single source of truth for translations used by both frontend and backend. + * + * Frontend (via Vite alias @i18n): + * import { messages } from '@i18n'; + * // pass `messages` to vue-i18n createI18n() + * + * Backend (CommonJS): + * const { t, hasKey, messages } = require('../../utils/modules/i18n'); + */ + +const en = require('./en'); +const de = require('./de'); + +const messages = { en, de }; + +// ── helpers (used by backend; frontend uses vue-i18n instead) ── + +function flattenObject(obj, prefix = '') { + const result = {}; + for (const key of Object.keys(obj)) { + const value = obj[key]; + const newKey = prefix ? `${prefix}.${key}` : key; + if (value && typeof value === 'object' && !Array.isArray(value)) { + Object.assign(result, flattenObject(value, newKey)); + } else { + result[newKey] = value; + } + } + return result; +} + +const flatCache = {}; +function getFlat(locale) { + if (!flatCache[locale]) { + flatCache[locale] = flattenObject(messages[locale] || messages.en); + } + return flatCache[locale]; +} + +function interpolate(text, params) { + if (!text || typeof text !== 'string') return text; + return text.replace(/\{(\w+)\}/g, (match, k) => + Object.prototype.hasOwnProperty.call(params, k) ? String(params[k]) : match + ); +} + +/** + * Translate a dot-notation key with optional interpolation. + * @param {string} key e.g. 'errors.auth.invalidCredentials' + * @param {Object} params e.g. { skill: 'summarization' } + * @param {string} locale defaults to 'en' + * @returns {string} + */ +function t(key, params = {}, locale = 'en') { + const flat = getFlat(locale); + if (Object.prototype.hasOwnProperty.call(flat, key)) { + return interpolate(flat[key], params); + } + return key; +} + +/** + * Check whether a translation key exists. + */ +function hasKey(key, locale = 'en') { + return Object.prototype.hasOwnProperty.call(getFlat(locale), key); +} + +module.exports = { messages, t, hasKey }; diff --git a/utils/modules/i18n/messages.js b/utils/modules/i18n/messages.js new file mode 100644 index 000000000..dca8cf995 --- /dev/null +++ b/utils/modules/i18n/messages.js @@ -0,0 +1,7 @@ +import en from './en/index.js' +import de from './de/index.js' + +const messages = { en, de } + +export { en, de, messages } +export default messages diff --git a/utils/modules/i18n/package.json b/utils/modules/i18n/package.json new file mode 100644 index 000000000..52504ee7a --- /dev/null +++ b/utils/modules/i18n/package.json @@ -0,0 +1,7 @@ +{ + "name": "care-i18n", + "version": "1.0.0", + "description": "Shared i18n translations for CARE frontend and backend", + "main": "index.js", + "license": "Apache-2.0" +} From 070e599abbc360871b2c62898f6e29e96142f1c4 Mon Sep 17 00:00:00 2001 From: Andrii Nikitin Date: Thu, 30 Apr 2026 04:13:19 +0200 Subject: [PATCH 02/92] refactor: adapt basic components for i18n --- frontend/package-lock.json | 72 ++++++++++++++++++++++++ frontend/package.json | 1 + frontend/src/basic/Loading.vue | 11 +++- frontend/src/basic/Modal.vue | 4 +- frontend/src/basic/Sidebar.vue | 6 +- frontend/src/basic/Toast.vue | 17 +++++- frontend/src/basic/navigation/Topbar.vue | 6 +- frontend/src/main.js | 16 +++++- frontend/vite.config.js | 1 + 9 files changed, 122 insertions(+), 12 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2a9803251..885f43122 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -43,6 +43,7 @@ "vite-plugin-html": "^3.2.2", "vue": "^3.5.29", "vue-3-socket.io": "^1.0.5", + "vue-i18n": "^9.14.4", "vue-router": "^5.0.3", "vue-style-loader": "^4.1.3", "vue-tab": "^0.0.0", @@ -1004,6 +1005,50 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@intlify/core-base": { + "version": "9.14.5", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.14.5.tgz", + "integrity": "sha512-5ah5FqZG4pOoHjkvs8mjtv+gPKYU0zCISaYNjBNNqYiaITxW8ZtVih3GS/oTOqN8d9/mDLyrjD46GBApNxmlsA==", + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "9.14.5", + "@intlify/shared": "9.14.5" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.14.5", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.14.5.tgz", + "integrity": "sha512-IHzgEu61/YIpQV5Pc3aRWScDcnFKWvQA9kigcINcCBXN8mbW+vk9SK+lDxA6STzKQsVJxUPg9ACC52pKKo3SVQ==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "9.14.5", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.14.5", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.14.5.tgz", + "integrity": "sha512-9gB+E53BYuAEMhbCAxVgG38EZrk59sxBtv3jSizNL2hEWlgjBjAw1AwpLHtNaeda12pe6W20OGEa0TwuMSRbyQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -7484,6 +7529,33 @@ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" } }, + "node_modules/vue-i18n": { + "version": "9.14.5", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.14.5.tgz", + "integrity": "sha512-0jQ9Em3ymWngyiIkj0+c/k7WgaPO+TNzjKSNq9BvBQaKJECqn9cd9fL4tkDhB5G1QBskGl9YxxbDAhgbFtpe2g==", + "deprecated": "v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "9.14.5", + "@intlify/shared": "9.14.5", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-i18n/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, "node_modules/vue-router": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.0.3.tgz", diff --git a/frontend/package.json b/frontend/package.json index 271625a37..20845e10a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -46,6 +46,7 @@ "vite": "^7.3.2", "vite-plugin-html": "^3.2.2", "vue": "^3.5.29", + "vue-i18n": "^9.14.4", "v-network-graph": "^0.9.7", "vue-3-socket.io": "^1.0.5", "vue-router": "^5.0.3", diff --git a/frontend/src/basic/Loading.vue b/frontend/src/basic/Loading.vue index 28ab8e16b..35feb2785 100644 --- a/frontend/src/basic/Loading.vue +++ b/frontend/src/basic/Loading.vue @@ -10,11 +10,11 @@ role="status" :style="'width:' + size + 'rem;height:'+ size + 'rem;'" > - {{ text }} + {{ displayText }}
- {{ text }} + {{ displayText }}
@@ -43,7 +43,7 @@ export default { 'text': { type: String, required: false, - default: "Loading..." + default: null }, 'textClass': { type: String, @@ -56,6 +56,11 @@ export default { default: 3, } }, + computed: { + displayText() { + return this.text ? this.text : this.$t('common.loading'); + } + } } diff --git a/frontend/src/basic/Modal.vue b/frontend/src/basic/Modal.vue index 408ddb28a..daa49c4d6 100644 --- a/frontend/src/basic/Modal.vue +++ b/frontend/src/basic/Modal.vue @@ -22,7 +22,7 @@ @@ -79,6 +77,7 @@ import Modal from "@/basic/Modal.vue"; import axios from "axios"; import getServerURL from "@/assets/serverUrl"; import BasicEditor from "@/basic/editor/Editor.vue"; +import { resolveApiMessage } from "@/assets/utils"; export default { name: "ConsentModal", @@ -88,7 +87,6 @@ export default { acceptStats: false, acceptDataSharing: false, isAtBottom: false, - modalVisible: false, }; }, computed: { @@ -114,24 +112,12 @@ export default { }, methods: { open() { - if (this.modalVisible) { - return; - } this.$refs.modal.open(); this.$nextTick(() => { // Check if content needs scrolling upon opening the modal this.checkScrollPosition(); }); }, - close() { - if (this.modalVisible) { - this.$refs.modal.close(); - } - }, - // Public method - isVisible() { - return this.modalVisible; - }, checkScrollPosition() { const container = this.$refs.termsContainer; if (!container) return; @@ -151,7 +137,7 @@ export default { }, async handleDecline() { this.resetForm(); - this.close(); + this.$refs.modal.close(); await axios.get(getServerURL() + "/auth/logout", {withCredentials: true}); await this.$router.push("/login"); }, @@ -164,17 +150,17 @@ export default { this.$socket.emit("userConsentUpdate", consentData, (res) => { if (res.success) { this.resetForm(); - this.close(); + this.$refs.modal.close(); this.$store.commit("auth/SET_USER", res.data); this.eventBus.emit("toast", { - title: "Terms successful updated", - message: "The terms are successfully updated", + title: this.$t('auth.messages.termsUpdated'), + message: this.$t('auth.messages.termsUpdatedMessage'), variant: "success", }); } else { this.eventBus.emit("toast", { - title: "Error in updating terms", - message: res.message, + title: this.$t('errors.auth.termsUpdateError'), + message: resolveApiMessage(res), variant: "danger", }); } @@ -184,12 +170,6 @@ export default { this.acceptStats = false; this.acceptDataSharing = false; }, - handleModalShow() { - this.modalVisible = true; - }, - handleModalHide() { - this.modalVisible = false; - }, }, }; diff --git a/frontend/src/auth/EmailVerificationModal.vue b/frontend/src/auth/EmailVerificationModal.vue index cc640975c..ddad9724a 100644 --- a/frontend/src/auth/EmailVerificationModal.vue +++ b/frontend/src/auth/EmailVerificationModal.vue @@ -2,12 +2,12 @@ @@ -54,6 +54,7 @@ import BasicModal from "@/basic/Modal.vue"; import BasicButton from "@/basic/Button.vue"; import axios from "axios"; import getServerURL from "@/assets/serverUrl"; +import { resolveApiMessage } from "@/assets/utils"; export default { name: "EmailVerificationModal", @@ -110,14 +111,14 @@ export default { if (response.status === 200) { this.emailVerification.showSuccess = true; - this.emailVerification.successMessage = response.data.message || "Verification email has been sent successfully."; + this.emailVerification.successMessage = resolveApiMessage(response.data, 'auth.messages.verificationEmailSent'); } else { this.emailVerification.showError = true; - this.emailVerification.errorMessage = response.data.message || "Failed to send verification email."; + this.emailVerification.errorMessage = resolveApiMessage(response.data, 'errors.auth.failedToSendVerificationEmail'); } - } catch (_error) { + } catch (error) { this.emailVerification.showError = true; - this.emailVerification.errorMessage = "An unexpected error occurred. Please try again."; + this.emailVerification.errorMessage = this.$t('errors.server.unexpectedError'); } finally { this.emailVerification.isLoading = false; } diff --git a/frontend/src/auth/ForgotPasswordModal.vue b/frontend/src/auth/ForgotPasswordModal.vue index 569210104..5dc4412e0 100644 --- a/frontend/src/auth/ForgotPasswordModal.vue +++ b/frontend/src/auth/ForgotPasswordModal.vue @@ -2,26 +2,26 @@ @@ -1148,29 +973,4 @@ export default { white-space: normal; word-break: break-word; } - -.table-wrapper thead th { - position: sticky; - top: 0; - z-index: 4; - background: var(--bs-body-bg, #fff); -} - -.table-wrapper thead th.table-fixed, -.table-wrapper thead th.table-fixed-left, -.table-wrapper thead th.table-fixed-right { - z-index: 6 !important; - background: var(--bs-body-bg, #fff); -} - -.table-wrapper thead th.table-fixed-right { - z-index: 7 !important; -} - -.table-wrapper tbody td.table-fixed, -.table-wrapper tbody td.table-fixed-left, -.table-wrapper tbody td.table-fixed-right { - z-index: 2 !important; - background: var(--bs-body-bg, #fff); -} diff --git a/frontend/src/basic/dashboard/Coordinator.vue b/frontend/src/basic/dashboard/Coordinator.vue index 0f3e9d0d2..a537a42a5 100644 --- a/frontend/src/basic/dashboard/Coordinator.vue +++ b/frontend/src/basic/dashboard/Coordinator.vue @@ -8,16 +8,14 @@ > diff --git a/frontend/src/basic/form/Element.vue b/frontend/src/basic/form/Element.vue index 1c9775203..651d95b39 100644 --- a/frontend/src/basic/form/Element.vue +++ b/frontend/src/basic/form/Element.vue @@ -4,10 +4,10 @@
@@ -15,9 +15,9 @@ v-if="'label' in options" :for="options.key" class="form-label" - >{{ options.label }} + >{{ translateText(options.label) }}
@@ -80,6 +80,12 @@ export default { this.eventBus.off('resetFormField', this.resetFieldState) }, methods: { + translateText(value) { + if (typeof value !== "string") { + return value; + } + return this.$te(value) ? this.$t(value) : value; + }, validate(data) { if (data === true) { this.invalidField = false; diff --git a/frontend/src/basic/form/Password.vue b/frontend/src/basic/form/Password.vue index 4215a5d29..378a27214 100644 --- a/frontend/src/basic/form/Password.vue +++ b/frontend/src/basic/form/Password.vue @@ -8,7 +8,7 @@ v-model="currentData" :class="options.class" :name="options.key" - :placeholder="options.placeholder" + :placeholder="translatedPlaceholder" :required="options.required" :pattern="options.pattern" :type="isPasswordVisible ? 'text' : 'password'" @@ -56,6 +56,15 @@ export default { isPasswordVisible: false, }; }, + computed: { + translatedPlaceholder() { + const placeholder = this.options.placeholder; + if (typeof placeholder !== "string") { + return placeholder; + } + return this.$te(placeholder) ? this.$t(placeholder) : placeholder; + }, + }, watch: { currentData() { this.$emit("update:modelValue", this.currentData); diff --git a/frontend/src/basic/form/Select.vue b/frontend/src/basic/form/Select.vue index c61c8c600..d27c09539 100644 --- a/frontend/src/basic/form/Select.vue +++ b/frontend/src/basic/form/Select.vue @@ -19,7 +19,7 @@ :value="valueAsObject ? option : option.value" :disabled="option.disabled" > - {{ option.name }} + {{ $te(option.name) ? $t(option.name) : option.name }} item.from === Number(this.currentData) ); if (mapping) { - return mapping.to; + return this.$te(mapping.to) ? this.$t(mapping.to) : mapping.to; } } return this.currentData; diff --git a/frontend/src/basic/form/Switch.vue b/frontend/src/basic/form/Switch.vue index 05de613c4..3e9d7d5e2 100644 --- a/frontend/src/basic/form/Switch.vue +++ b/frontend/src/basic/form/Switch.vue @@ -14,9 +14,9 @@ v-if="'label' in options" :for="options.key" class="form-label" - >{{ options.label }} + >{{ $te(options.label) ? $t(options.label) : options.label }} diff --git a/frontend/src/basic/form/Textarea.vue b/frontend/src/basic/form/Textarea.vue index e17cc3998..2d9c11b43 100644 --- a/frontend/src/basic/form/Textarea.vue +++ b/frontend/src/basic/form/Textarea.vue @@ -7,7 +7,7 @@ :required="options.required" :class="options.class" class="form-control" - :placeholder="options.placeholder" + :placeholder="translatedPlaceholder" :disabled="(options.readOnly !== undefined || options.disabled !== undefined)" @blur="blur(currentData)" /> @@ -38,6 +38,15 @@ export default { currentData: "", } }, + computed: { + translatedPlaceholder() { + const placeholder = this.options.placeholder; + if (typeof placeholder !== "string") { + return placeholder; + } + return this.$te(placeholder) ? this.$t(placeholder) : placeholder; + }, + }, watch: { currentData() { this.$emit("update:modelValue", this.currentData); diff --git a/frontend/src/basic/icon/IconLoading.vue b/frontend/src/basic/icon/IconLoading.vue index 43fad3e8b..bdc0428c4 100644 --- a/frontend/src/basic/icon/IconLoading.vue +++ b/frontend/src/basic/icon/IconLoading.vue @@ -4,7 +4,7 @@ :style="'width: ' + size + 'px; height: ' + size + 'px;'" role="status" > - Loading... + {{ $t('common.loading') }}
diff --git a/frontend/src/basic/modal/ApplySkillSetupStepper.vue b/frontend/src/basic/modal/ApplySkillSetupStepper.vue index 38835a309..9933a02e1 100644 --- a/frontend/src/basic/modal/ApplySkillSetupStepper.vue +++ b/frontend/src/basic/modal/ApplySkillSetupStepper.vue @@ -4,12 +4,12 @@ ref="applySkillsStepper" :steps="stepperSteps" :validation="stepValid" - submit-text="Apply Skills" + :submit-text="$t('nlp.preprocessing.setupStepper.title')" @submit="applySkills" @close-requested="handleCloseRequest" >