diff --git a/CLAUDE.md b/CLAUDE.md index c2ffac6..96220cf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -231,6 +231,8 @@ legalconsenthub/ │ │ ├── permissions.global.ts # Authorization check │ │ └── refreshToken.global.ts # Token refresh logic │ ├── pages/ # Route pages +│ │ ├── settings.vue # User settings page (language, theme, appearance) +│ │ ├── administration.vue # Admin template editor │ │ ├── application-forms/ │ │ ├── callback.vue # OAuth callback │ │ ├── create.vue diff --git a/legalconsenthub/app/app.vue b/legalconsenthub/app/app.vue index 57b60a6..df7550f 100644 --- a/legalconsenthub/app/app.vue +++ b/legalconsenthub/app/app.vue @@ -1,5 +1,5 @@ - diff --git a/legalconsenthub/app/components/NotificationsSlideover.vue b/legalconsenthub/app/components/NotificationsSlideover.vue index a7e501f..f98e0a7 100644 --- a/legalconsenthub/app/components/NotificationsSlideover.vue +++ b/legalconsenthub/app/components/NotificationsSlideover.vue @@ -1,9 +1,9 @@ - Submit - Edit comment - Cancel + + {{ $t('comments.submit') }} + + {{ $t('comments.edit') }} + {{ $t('common.cancel') }} diff --git a/legalconsenthub/app/utils/formDiff.ts b/legalconsenthub/app/utils/formDiff.ts index 8a7a480..6ae3de8 100644 --- a/legalconsenthub/app/utils/formDiff.ts +++ b/legalconsenthub/app/utils/formDiff.ts @@ -74,7 +74,7 @@ function flattenFormElements(form: ApplicationFormDto): Array<{ element: FormEle for (const section of form.formElementSections) { for (const subsection of section.formElementSubSections) { for (const element of subsection.formElements) { - elements.push({ element, sectionTitle: section.title }) + elements.push({ element, sectionTitle: section.title }) } } } @@ -88,7 +88,7 @@ function flattenSnapshotElements( for (const section of snapshot.sections) { for (const subsection of section.subsections) { for (const element of subsection.elements) { - elements.push({ element, sectionTitle: section.title }) + elements.push({ element, sectionTitle: section.title }) } } } @@ -110,7 +110,7 @@ function compareElements( position: number ): ElementModification | null { const optionsDiff = compareOptions(current.options, version.options) - + if (optionsDiff.added.length > 0 || optionsDiff.removed.length > 0 || optionsDiff.modified.length > 0) { return { sectionTitle, diff --git a/legalconsenthub/i18n/locales/de.json b/legalconsenthub/i18n/locales/de.json index 83e5777..730c569 100644 --- a/legalconsenthub/i18n/locales/de.json +++ b/legalconsenthub/i18n/locales/de.json @@ -1,10 +1,160 @@ { - "roles": { - "admin": "Administrator", - "employee": "Arbeitnehmer", - "employer": "Arbeitgeber", - "worksCouncilMember": "Betriebsratsmitglied", - "worksCouncilChair": "Betriebsratsvorsitzender" + "applicationForms": { + "title": "Mitbestimmungsanträge", + "createNew": "Neuer Mitbestimmungsantrag", + "noFormsAvailable": "Keine Anträge vorhanden", + "noPermission": "Keine Berechtigung", + "noPermissionDescription": "Sie haben keine Berechtigung zum Erstellen von Anträgen.", + "backToOverview": "Zurück zur Übersicht", + "deleteConfirm": "Möchten Sie wirklich den Mitbestimmungsantrag \"{name}\" löschen?", + "deleteTitle": "Mitbestimmungsantrag löschen", + "lastEditedBy": "Zuletzt bearbeitet von", + "createdBy": "Erstellt von", + "saved": "Antrag erfolgreich gespeichert", + "submitted": "Antrag erfolgreich eingereicht", + "deleted": "Antrag erfolgreich gelöscht", + "formElements": { + "comments": "Kommentare", + "addInputBelow": "Eingabefeld hinzufügen", + "selectPlaceholder": "Status auswählen", + "title": "Titel", + "text": "Text", + "unimplemented": "Element nicht implementiert:" + }, + "status": { + "draft": "Entwurf", + "submitted": "Eingereicht", + "approved": "Genehmigt", + "rejected": "Abgelehnt", + "signed": "Signiert" + }, + "navigation": { + "previous": "Zurück", + "next": "Weiter", + "save": "Speichern", + "submit": "Einreichen" + } + }, + "templates": { + "title": "Vorlagen", + "editorTitle": "Administration - JSON Template Editor", + "newTemplate": "Neue Vorlage", + "reset": "Zurücksetzen", + "unsavedChanges": "Ungespeicherte Änderungen", + "noTemplateFound": "Keine Vorlage gefunden. Erstellen Sie eine neue Vorlage.", + "invalidJson": "Ungültiges JSON", + "invalidJsonDescription": "Das JSON-Format ist ungültig. Bitte korrigieren Sie die Syntax.", + "lastModified": "Zuletzt bearbeitet am", + "created": "Vorlage erfolgreich erstellt", + "updated": "Vorlage erfolgreich aktualisiert", + "saveError": "Fehler beim Speichern der Vorlage", + "unsavedWarning": "Sie haben ungespeicherte Änderungen. Möchten Sie die Seite wirklich verlassen?" + }, + "versions": { + "title": "Versionen", + "pageTitle": "Versionen: {name}", + "empty": "Keine Versionen verfügbar", + "loading": "Versionen werden geladen...", + "loadError": "Fehler beim Laden der Versionen", + "loadErrorDescription": "Versionen konnten nicht geladen werden", + "unknownError": "Unbekannter Fehler", + "compare": "Vergleichen", + "restore": "Wiederherstellen", + "restored": "Erfolg", + "restoredDescription": "Das Formular wurde auf die ausgewählte Version zurückgesetzt.", + "restoreError": "Version konnte nicht wiederhergestellt werden", + "restoreTitle": "Version wiederherstellen", + "restoreConfirm": "Möchten Sie Version v{number} wirklich wiederherstellen?", + "restoreDescription": "Dies erstellt eine neue Version mit dem Inhalt der ausgewählten Version. Die aktuelle Version und alle Änderungen bleiben in der Historie erhalten.", + "comparisonTitle": "Vergleich: Aktuelles Formular mit Version v{number}", + "comparisonError": "Fehler beim Laden der Version", + "elementsAdded": "Hinzugefügte Elemente ({count})", + "elementsRemoved": "Entfernte Elemente ({count})", + "elementsModified": "Geänderte Elemente ({count})", + "elementWithoutTitle": "Ohne Titel", + "elementIn": "Element in", + "optionsAdded": "Optionen hinzugefügt ({count})", + "optionsRemoved": "Optionen entfernt ({count})", + "optionsModified": "Optionen geändert ({count})", + "noChanges": "Keine Unterschiede gefunden" + }, + "comments": { + "title": "Kommentare", + "empty": "Keine Kommentare vorhanden", + "submit": "Absenden", + "edit": "Kommentar bearbeiten", + "editAction": "Bearbeiten" + }, + "compliance": { + "title": "Compliance-Status", + "critical": "Kritisch", + "warning": "Warnung", + "nonCritical": "Unkritisch" + }, + "notifications": { + "title": "Benachrichtigungen", + "empty": "Keine Benachrichtigungen", + "unreadCount": "{count} ungelesen", + "tooltip": "Benachrichtigungen" + }, + "administration": { + "title": "Administration", + "accessDenied": "Zugriff verweigert" + }, + "user": { + "administration": "Administration", + "settings": "Einstellungen", + "logout": "Abmelden" + }, + "settings": { + "title": "Einstellungen", + "language": { + "title": "Sprache", + "description": "Wählen Sie Ihre bevorzugte Sprache" + }, + "appearance": { + "title": "Erscheinungsbild", + "description": "Wählen Sie zwischen hellem und dunklem Modus", + "light": "Hell", + "dark": "Dunkel" + }, + "theme": { + "title": "Farbschema", + "description": "Passen Sie die Farben der Anwendung an", + "primary": "Primärfarbe", + "neutral": "Neutralfarbe" + } + }, + "organization": { + "current": "Aktuelle Organisation" + }, + "auth": { + "welcome": "Willkommen", + "redirectMessage": "Sie werden zur Authentifizierung zu Keycloak weitergeleitet", + "signIn": "Mit Keycloak anmelden", + "termsAgreement": "Mit der Anmeldung stimmen Sie unseren Nutzungsbedingungen zu", + "login": "Anmelden" + }, + "error": { + "pageNotFound": "Seite nicht gefunden", + "pageNotFoundDescription": "Es tut uns leid, aber diese Seite konnte nicht gefunden werden." + }, + "common": { + "save": "Speichern", + "cancel": "Abbrechen", + "delete": "Löschen", + "edit": "Bearbeiten", + "close": "Schließen", + "confirm": "Bestätigen", + "back": "Zurück", + "loading": "Laden...", + "error": "Fehler", + "success": "Erfolg", + "name": "Name", + "home": "Home", + "type": "Typ", + "general": "Allgemein", + "on": "am" }, "serverConnection": { "title": "Verbindung zum Server unterbrochen", @@ -13,5 +163,12 @@ "lastCheck": "Letzte Überprüfung", "retryInfo": "Automatischer Wiederholungsversuch alle 60 Sekunden", "retryNow": "Jetzt erneut versuchen" + }, + "roles": { + "admin": "Administrator", + "employee": "Arbeitnehmer", + "employer": "Arbeitgeber", + "worksCouncilMember": "Betriebsratsmitglied", + "worksCouncilChair": "Betriebsratsvorsitzender" } } diff --git a/legalconsenthub/i18n/locales/en.json b/legalconsenthub/i18n/locales/en.json index 66e18e7..15dd78d 100644 --- a/legalconsenthub/i18n/locales/en.json +++ b/legalconsenthub/i18n/locales/en.json @@ -1,10 +1,160 @@ { - "roles": { - "admin": "Administrator", - "employee": "Employee", - "employer": "Employer", - "worksCouncilMember": "Works Council Member", - "worksCouncilChair": "Works Council Chair" + "applicationForms": { + "title": "Co-determination Applications", + "createNew": "New Co-determination Application", + "noFormsAvailable": "No applications available", + "noPermission": "No Permission", + "noPermissionDescription": "You do not have permission to create applications.", + "backToOverview": "Back to Overview", + "deleteConfirm": "Do you really want to delete the co-determination application \"{name}\"?", + "deleteTitle": "Delete Co-determination Application", + "lastEditedBy": "Last edited by", + "createdBy": "Created by", + "saved": "Application form saved", + "submitted": "Application form submitted", + "deleted": "Application form deleted", + "formElements": { + "comments": "Comments", + "addInputBelow": "Add input field below", + "selectPlaceholder": "Select status", + "title": "Title", + "text": "Text", + "unimplemented": "Element unimplemented:" + }, + "status": { + "draft": "Draft", + "submitted": "Submitted", + "approved": "Approved", + "rejected": "Rejected", + "signed": "Signed" + }, + "navigation": { + "previous": "Previous", + "next": "Next", + "save": "Save", + "submit": "Submit" + } + }, + "templates": { + "title": "Templates", + "editorTitle": "Administration - JSON Template Editor", + "newTemplate": "New Template", + "reset": "Reset", + "unsavedChanges": "Unsaved Changes", + "noTemplateFound": "No template found. Create a new template.", + "invalidJson": "Invalid JSON", + "invalidJsonDescription": "The JSON format is invalid. Please correct the syntax.", + "lastModified": "Last edited on", + "created": "Template successfully created", + "updated": "Template successfully updated", + "saveError": "Error saving template", + "unsavedWarning": "You have unsaved changes. Do you really want to leave this page?" + }, + "versions": { + "title": "Versions", + "pageTitle": "Versions: {name}", + "empty": "No versions available", + "loading": "Loading versions...", + "loadError": "Error loading versions", + "loadErrorDescription": "Versions could not be loaded", + "unknownError": "Unknown error", + "compare": "Compare", + "restore": "Restore", + "restored": "Success", + "restoredDescription": "The form has been restored to the selected version.", + "restoreError": "Version could not be restored", + "restoreTitle": "Restore Version", + "restoreConfirm": "Do you really want to restore version v{number}?", + "restoreDescription": "This will create a new version with the content of the selected version. The current version and all changes will remain in the history.", + "comparisonTitle": "Comparison: Current Form with Version v{number}", + "comparisonError": "Error loading version", + "elementsAdded": "Added Elements ({count})", + "elementsRemoved": "Removed Elements ({count})", + "elementsModified": "Modified Elements ({count})", + "elementWithoutTitle": "Without Title", + "elementIn": "Element in", + "optionsAdded": "Options added ({count})", + "optionsRemoved": "Options removed ({count})", + "optionsModified": "Options modified ({count})", + "noChanges": "No differences found" + }, + "comments": { + "title": "Comments", + "empty": "No comments available", + "submit": "Submit", + "edit": "Edit Comment", + "editAction": "Edit" + }, + "compliance": { + "title": "Compliance Status", + "critical": "Critical", + "warning": "Warning", + "nonCritical": "Non-critical" + }, + "notifications": { + "title": "Notifications", + "empty": "No notifications", + "unreadCount": "{count} unread", + "tooltip": "Notifications" + }, + "administration": { + "title": "Administration", + "accessDenied": "Access denied" + }, + "user": { + "administration": "Administration", + "settings": "Settings", + "logout": "Log out" + }, + "settings": { + "title": "Settings", + "language": { + "title": "Language", + "description": "Choose your preferred language" + }, + "appearance": { + "title": "Appearance", + "description": "Choose between light and dark mode", + "light": "Light", + "dark": "Dark" + }, + "theme": { + "title": "Color Theme", + "description": "Customize the application colors", + "primary": "Primary Color", + "neutral": "Neutral Color" + } + }, + "organization": { + "current": "Current Organization" + }, + "auth": { + "welcome": "Welcome", + "redirectMessage": "You will be redirected to Keycloak to authenticate", + "signIn": "Sign in with Keycloak", + "termsAgreement": "By signing in, you agree to our terms of service", + "login": "Login" + }, + "error": { + "pageNotFound": "Page not found", + "pageNotFoundDescription": "We are sorry but this page could not be found." + }, + "common": { + "save": "Save", + "cancel": "Cancel", + "delete": "Delete", + "edit": "Edit", + "close": "Close", + "confirm": "Confirm", + "back": "Back", + "loading": "Loading...", + "error": "Error", + "success": "Success", + "name": "Name", + "home": "Home", + "type": "Type", + "general": "General", + "on": "on" }, "serverConnection": { "title": "Server Connection Lost", @@ -13,5 +163,12 @@ "lastCheck": "Last check", "retryInfo": "Automatic retry every 60 seconds", "retryNow": "Try again now" + }, + "roles": { + "admin": "Administrator", + "employee": "Employee", + "employer": "Employer", + "worksCouncilMember": "Works Council Member", + "worksCouncilChair": "Works Council Chair" } } diff --git a/legalconsenthub/nuxt.config.ts b/legalconsenthub/nuxt.config.ts index 176bce4..b7b17fe 100644 --- a/legalconsenthub/nuxt.config.ts +++ b/legalconsenthub/nuxt.config.ts @@ -28,6 +28,7 @@ export default defineNuxtConfig({ ], i18n: { defaultLocale: 'de', + strategy: 'no_prefix', locales: [ { code: 'en', name: 'English', file: 'en.json' }, { code: 'de', name: 'Deutsch', file: 'de.json' } diff --git a/legalconsenthub/types/formDiff.ts b/legalconsenthub/types/formDiff.ts index 49f3b81..5fbdc6d 100644 --- a/legalconsenthub/types/formDiff.ts +++ b/legalconsenthub/types/formDiff.ts @@ -28,4 +28,3 @@ export interface OptionModification { value: string labelChanged: { from: string; to: string } } -