From 96c40d5f49f0ad157a4d3ba2bc06f35647b4e2ee Mon Sep 17 00:00:00 2001 From: Nikolai Giman Date: Sat, 16 May 2026 11:01:54 +0200 Subject: [PATCH] feat: new locale Deutsch --- web/src/components/UserMenu.vue | 9 + web/src/locales/de.ts | 737 ++++++++++++++++++++++++++++++++ web/src/locales/index.ts | 4 +- 3 files changed, 749 insertions(+), 1 deletion(-) create mode 100644 web/src/locales/de.ts diff --git a/web/src/components/UserMenu.vue b/web/src/components/UserMenu.vue index bcecb41..cd772d6 100644 --- a/web/src/components/UserMenu.vue +++ b/web/src/components/UserMenu.vue @@ -244,6 +244,15 @@ const items = computed(() => [ saveLocale('ru') }, }, + { + label: 'Deutsch', + type: 'checkbox', + checked: locale.value === 'de', + onSelect(e: Event) { + e.preventDefault() + saveLocale('de') + }, + }, ], }, { diff --git a/web/src/locales/de.ts b/web/src/locales/de.ts new file mode 100644 index 0000000..08d030d --- /dev/null +++ b/web/src/locales/de.ts @@ -0,0 +1,737 @@ +export default { + auth: { + welcome: 'Willkommen zurück', + signInToAccount: 'Melden Sie sich bei Ihrem Konto an', + continueWithGoogle: 'Mit Google fortfahren', + continueWithGithub: 'Mit GitHub fortfahren', + continueWithApple: 'Mit Apple fortfahren', + orContinueWith: 'Oder fortfahren mit', + magicLink: 'Magic Link', + password: 'Passwort', + termsText: 'Indem Sie fortfahren, stimmen Sie unseren', + termsOfService: 'Nutzungsbedingungen', + and: 'und', + privacyPolicy: 'Datenschutzerklärung', + + // Login by code + email: 'E-Mail', + emailPlaceholder: 'sie{\'@\'}beispiel.com', + sendCode: 'Code senden', + codeSent: 'Code gesendet', + checkInbox: 'Überprüfen Sie Ihr Postfach unter {email}', + enterCode: 'Geben Sie den 6-stelligen Code ein, der gesendet wurde an', + verificationCode: 'Bestätigungscode', + verifyAndSignIn: 'Bestätigen & Anmelden', + back: 'Zurück', + resendCode: 'Code erneut senden', + codeResent: 'Code erneut gesendet', + newCodeSent: 'Neuer Code an {email} gesendet', + + // Login by password + login: 'Anmeldung', + loginPlaceholder: 'Benutzername oder E-Mail', + passwordLabel: 'Passwort', + passwordPlaceholder: 'Ihr Passwort', + forgotPassword: 'Passwort vergessen?', + signIn: 'Anmelden', + + // Forgot password + forgotPasswordTitle: 'Passwort zurücksetzen', + forgotPasswordDescription: 'Geben Sie Ihre E-Mail-Adresse ein, und wir senden Ihnen einen Link zum Zurücksetzen Ihres Passworts.', + sendResetLink: 'Reset-Link senden', + backToLogin: 'Zurück zur Anmeldung', + checkYourEmail: 'Überprüfen Sie Ihre E-Mails', + resetLinkSent: 'Wir haben einen Link zum Zurücksetzen des Passworts gesendet an', + emailSent: 'E-Mail gesendet', + checkInboxForReset: 'Überprüfen Sie Ihr Postfach auf den Link zum Zurücksetzen des Passworts', + + // Reset password + setNewPassword: 'Neues Passwort festlegen', + setNewPasswordDescription: 'Geben Sie ein neues Passwort für Ihr Konto ein.', + newPassword: 'Neues Passwort', + newPasswordPlaceholder: 'Neues Passwort eingeben', + confirmPassword: 'Passwort bestätigen', + confirmPasswordPlaceholder: 'Neues Passwort wiederholen', + resetPassword: 'Passwort zurücksetzen', + passwordReset: 'Passwort zurückgesetzt', + passwordResetSuccess: 'Ihr Passwort wurde erfolgreich geändert. Sie können sich jetzt anmelden.', + invalidResetLink: 'Ungültiger Link', + invalidResetLinkDescription: 'Der Link zum Zurücksetzen des Passworts ist ungültig oder abgelaufen.', + canNotResetPassword: 'Passwort konnte nicht zurückgesetzt werden. Bitte versuchen Sie es erneut.', + passwordTooShort: 'Das Passwort muss mindestens 6 Zeichen lang sein', + passwordsDoNotMatch: 'Passwörter stimmen nicht überein', + + // Messages + success: 'Erfolg', + error: 'Fehler', + loggedIn: 'Willkommen bei TaskView', + invalidCode: 'Ungültiger Code. Bitte versuchen Sie es erneut.', + invalidCredentials: 'Ungültige Anmeldedaten oder Passwort', + loginFailed: 'Anmeldung fehlgeschlagen. Bitte versuchen Sie es erneut.', + failedToSendCode: 'Code konnte nicht gesendet werden. Bitte versuchen Sie es erneut.', + failedToResendCode: 'Code konnte nicht erneut gesendet werden', + failedToSendResetLink: 'Reset-Link konnte nicht gesendet werden. Bitte versuchen Sie es erneut.', + + // SSO + ssoSignIn: 'Mit SSO anmelden', + ssoNotFound: 'SSO nicht konfiguriert', + ssoNotFoundDescription: 'Kein SSO-Anbieter für die Domain {domain} gefunden', + ssoError: 'SSO-Authentifizierung fehlgeschlagen. Bitte versuchen Sie es erneut.', + + // Validation + invalidEmail: 'Ungültige E-Mail-Adresse', + loginRequired: 'Anmeldung erforderlich', + passwordRequired: 'Passwort erforderlich', + codeMustBe6: 'Der Code muss 6 Zeichen lang sein', + }, + projects: { + title: 'Projekte', + project: 'Projekt', + selectProject: 'Projekt auswählen', + edit: 'Projekt bearbeiten', + name: 'Name', + namePlaceholder: 'Projektnamen eingeben', + description: 'Beschreibung', + descriptionPlaceholder: 'Projektbeschreibung eingeben', + deleteConfirm: 'Projekt löschen', + deleteMessage: 'Sind Sie sicher, dass Sie das Projekt "{name}" löschen möchten? Der gesamte Projektverlauf wird gelöscht, einschließlich Aufgaben- und Listenverlauf. Diese Aktion kann nicht rückgängig gemacht werden.', + addPlaceholder: 'Projektnamen eingeben', + add: 'Projekt hinzufügen', + }, + contextMenu: { + kanban: 'Kanban', + graph: 'Graph', + collaboration: 'Zusammenarbeit', + integrations: 'Integrationen', + webhooks: 'Webhooks', + timeReports: 'Zeitberichte', + edit: 'Bearbeiten', + moveToArchive: 'Ins Archiv verschieben', + restoreFromArchive: 'Aus dem Archiv wiederherstellen', + delete: 'Löschen', + }, + archive: { + title: 'Archiv', + }, + lists: { + title: 'Listen', + selectList: 'Liste auswählen', + selectListToViewTasks: 'Wählen Sie eine Liste, um Aufgaben anzuzeigen', + addPlaceholder: 'Listennamen eingeben', + add: 'Liste hinzufügen', + edit: 'Liste bearbeiten', + name: 'Name', + namePlaceholder: 'Listennamen eingeben', + deleteConfirm: 'Liste löschen', + deleteMessage: 'Sind Sie sicher, dass Sie die Liste "{name}" löschen möchten? Die Liste wird gelöscht, einschließlich ihres Bearbeitungsverlaufs sowie aller Aufgaben in der Liste und deren Verlaufs. Diese Aktion kann nicht rückgängig gemacht werden.', + }, + common: { + cancel: 'Abbrechen', + save: 'Speichern', + delete: 'Löschen', + done: 'Fertig', + yes: 'Ja', + no: 'Nein', + loading: 'Wird geladen...', + close: 'Schließen', + add: 'Hinzufügen', + }, + kanban: { + title: 'Kanban', + description: 'Kanban-Board-Ansicht in Kürze verfügbar', + addColumn: 'Spalte hinzufügen', + addTask: 'Aufgabe hinzufügen', + edit: 'Bearbeiten', + delete: 'Löschen', + deleteColumn: 'Spalte löschen', + deleteColumnConfirm: 'Sind Sie sicher, dass Sie diese Spalte löschen möchten? Aufgaben werden in den Backlog verschoben.', + editColumn: 'Spalte bearbeiten', + columnName: 'Spaltenname', + loadMore: 'Mehr laden', + }, + msg: { + allTasks: 'Backlog', + todayTasks: 'Heute', + upcomingTasks: 'Anstehend', + lastTasks: 'Aktuelle Aufgaben', + todayExplanation: 'Aufgaben mit Fälligkeit heute oder früher', + upcomingExplanation: 'Aufgaben mit Fälligkeit in naher Zukunft', + lastAddedTasksExplanation: 'Kürzlich hinzugefügte Aufgaben ohne Fälligkeitsdatum', + lastCompletedTasksExplanation: 'Kürzlich abgeschlossene Aufgaben', + pending: 'Aktiv', + completed: 'Abgeschlossen', + noTasks: 'Keine Aufgaben', + addTask: 'Aufgabe hinzufügen', + addTaskToToday: 'Aufgabe für heute hinzufügen', + addTaskToUpcoming: 'Anstehende Aufgabe hinzufügen', + addFirstProject: 'Fügen Sie Ihr erstes Projekt hinzu', + today: 'Heute', + lastAddedTasks: 'Hinzugefügt', + lastCompletedTasks: 'Abgeschlossen', + }, + admin: { + search: 'Aufgaben suchen...', + }, + motivationToday: [ + 'Ein toller Tag für Produktivität!', + 'Heute ist Ihr Tag!', + 'Fangen Sie mit etwas Kleinem an!', + 'Jede Aufgabe ist ein Schritt nach vorn!', + ], + motivationUpcoming: [ + 'Planen Sie voraus!', + 'Die Zukunft liegt in Ihren Händen!', + 'Bereiten Sie sich auf den Erfolg vor!', + 'Spannende Dinge stehen bevor!', + ], + deadline: { + startDate: 'Startdatum', + endDate: 'Enddatum', + selectTime: 'Zeit auswählen', + today: 'Heute', + tomorrow: 'Morgen', + yesterday: 'Gestern', + thisWeek: 'Diese Woche', + thisMonth: 'Diesen Monat', + }, + graph: { + title: 'Graph', + description: 'Graphansicht in Kürze verfügbar', + addTask: 'Aufgabe hinzufügen', + selectedEdge: 'Kante ausgewählt', + }, + collaboration: { + title: 'Zusammenarbeit', + description: 'Funktionen zur Zusammenarbeit in Kürze verfügbar', + selectProject: 'Wählen Sie ein Projekt, um die Zusammenarbeit zu verwalten', + tabs: { + members: 'Mitglieder', + roles: 'Rollen', + }, + members: { + title: 'Teammitglieder', + add: 'Mitglied hinzufügen', + invite: 'Mitglied hinzufügen', + email: 'E-Mail-Adresse', + emailPlaceholder: 'kollege{\'@\'}beispiel.com', + sendInvite: 'Einladung senden', + pending: 'Ausstehend', + owner: 'Inhaber', + invitedAt: 'Eingeladen', + noRoles: 'Keine Rollen zugewiesen', + assignRoles: 'Rollen zuweisen', + selectRoles: 'Rollen für dieses Mitglied auswählen', + resendInvite: 'Einladung erneut senden', + remove: 'Mitglied entfernen', + empty: 'Noch keine Teammitglieder. Fügen Sie jemanden zur Zusammenarbeit hinzu!', + }, + roles: { + title: 'Rollen', + create: 'Rolle erstellen', + name: 'Rollenname', + namePlaceholder: 'Rollennamen eingeben', + permissionsCount: '{count} Berechtigungen', + system: 'System', + assignPermissions: 'Berechtigungen zuweisen', + systemRoleWarning: 'Systemrollen können nicht geändert werden', + deleteConfirm: 'Rolle löschen', + deleteMessage: 'Sind Sie sicher, dass Sie "{name}" löschen möchten? Mitglieder mit dieser Rolle müssen neu zugewiesen werden.', + empty: 'Noch keine benutzerdefinierten Rollen. Erstellen Sie eine, um spezifische Berechtigungen zu definieren.', + }, + permissions: { + searchPlaceholder: 'Berechtigungen suchen...', + groups: { + tasks: 'Aufgaben', + lists: 'Listen', + members: 'Mitglieder', + roles: 'Rollen', + }, + view_tasks: 'Aufgaben anzeigen', + view_tasksDesc: 'Kann Aufgaben im Projekt anzeigen', + create_tasks: 'Aufgaben erstellen', + create_tasksDesc: 'Kann neue Aufgaben erstellen', + edit_tasks: 'Aufgaben bearbeiten', + edit_tasksDesc: 'Kann vorhandene Aufgaben bearbeiten', + delete_tasks: 'Aufgaben löschen', + delete_tasksDesc: 'Kann Aufgaben löschen', + view_lists: 'Listen anzeigen', + view_listsDesc: 'Kann Listen im Projekt anzeigen', + create_lists: 'Listen erstellen', + create_listsDesc: 'Kann neue Listen erstellen', + edit_lists: 'Listen bearbeiten', + edit_listsDesc: 'Kann vorhandene Listen bearbeiten', + delete_lists: 'Listen löschen', + delete_listsDesc: 'Kann Listen löschen', + view_members: 'Mitglieder anzeigen', + view_membersDesc: 'Kann Projektmitglieder anzeigen', + invite_members: 'Mitglieder einladen', + invite_membersDesc: 'Kann neue Mitglieder einladen', + remove_members: 'Mitglieder entfernen', + remove_membersDesc: 'Kann Mitglieder aus dem Projekt entfernen', + view_roles: 'Rollen anzeigen', + view_rolesDesc: 'Kann Rollen anzeigen', + manage_roles: 'Rollen verwalten', + manage_rolesDesc: 'Kann Rollen erstellen, bearbeiten und löschen', + }, + }, + integrations: { + title: 'Integrationen', + selectProject: 'Wählen Sie ein Projekt, um Integrationen zu verwalten', + add: 'Integration hinzufügen', + addTitle: 'Repository verbinden', + connectDescription: 'Wählen Sie einen Anbieter, um Ihr Repository zu verbinden.', + provider: 'Anbieter', + repoFullName: 'Repository', + repoPlaceholder: 'inhaber/repository', + empty: 'Noch keine Integrationen. Verbinden Sie ein GitHub- oder GitLab-Repository, um Issues zu synchronisieren.', + selectRepo: 'Repository auswählen', + searchRepos: 'Repositories suchen...', + noReposFound: 'Keine Repositories gefunden', + pendingSelectRepo: 'Repository nicht ausgewählt', + private: 'Privat', + syncFailed: 'Issue-Synchronisierung fehlgeschlagen', + syncFailedDescription: 'Das Issue konnte auf dem Remote-Repository nicht aktualisiert werden. Verwenden Sie die Synchronisierungsschaltfläche auf der Integrationsseite, um es erneut zu versuchen.', + sync: 'Synchronisieren', + syncing: 'Wird synchronisiert...', + }, + webhooks: { + title: 'Webhooks', + selectProject: 'Wählen Sie ein Projekt, um Webhooks zu verwalten', + add: 'Webhook hinzufügen', + empty: 'Noch keine Webhooks. Fügen Sie einen Webhook hinzu, um Ereignisbenachrichtigungen zu erhalten.', + url: 'URL', + urlPlaceholder: 'https://beispiel.com/webhook', + events: 'Ereignisse', + selectEvents: 'Ereignisse auswählen', + test: 'Test', + deliveries: 'Auslieferungen', + noDeliveries: 'Noch keine Auslieferungen', + rotateSecret: 'Secret rotieren', + secretTitle: 'Webhook-Secret', + secretDescription: 'Kopieren Sie dieses Secret und bewahren Sie es sicher auf. Es wird nicht erneut angezeigt.', + event: 'Ereignis', + status: 'Status', + httpCode: 'HTTP-Code', + attempts: 'Versuche', + time: 'Zeit', + payload: 'Payload', + viewPayload: 'Payload anzeigen', + copy: 'Kopieren', + edit: 'Bearbeiten', + allStatuses: 'Alle Status', + rotateConfirm: 'Sind Sie sicher, dass Sie das Secret rotieren möchten? Das aktuelle Secret funktioniert sofort nicht mehr und alle Webhook-Konsumenten müssen mit dem neuen Secret aktualisiert werden.', + }, + main: 'Start', + mainScreen: { + welcome: 'Willkommen', + selectProject: 'Wählen Sie ein Projekt aus der Seitenleiste, um zu beginnen', + }, + tasks: { + amount: 'Betrag', + enterAmount: 'Betrag eingeben', + noTransactionType: 'Transaktionstyp', + income: 'Einnahme', + expense: 'Ausgabe', + allTasks: 'Alle Aufgaben', + addPlaceholder: 'Aufgabennamen eingeben', + searchPlaceholder: 'Aufgaben suchen...', + add: 'Aufgabe hinzufügen', + details: 'Aufgabendetails', + description: 'Beschreibung', + addDescription: 'Beschreibung hinzufügen...', + note: 'Notiz', + addNote: 'Notiz hinzufügen...', + priority: 'Priorität', + priorityNone: 'Keine Priorität', + priorityLow: 'Niedrig', + priorityMedium: 'Mittel', + priorityHigh: 'Hoch', + dueDate: 'Fälligkeitsdatum', + deadline: 'Frist', + addDueDate: 'Fälligkeitsdatum hinzufügen', + assignees: 'Zugewiesene', + selectAssignees: 'Zugewiesene auswählen', + searchUsers: 'Benutzer suchen...', + noUsersAvailable: 'Keine Benutzer verfügbar', + list: 'Liste', + selectList: 'Liste auswählen', + searchLists: 'Listen suchen...', + noList: 'Keine Liste', + status: 'Status', + selectStatus: 'Status auswählen', + searchStatuses: 'Status suchen...', + noStatus: 'Kein Status', + tags: 'Tags', + addTag: 'Tag hinzufügen', + subtasks: 'Unteraufgaben', + addSubtask: 'Unteraufgabe hinzufügen', + notFound: 'Aufgabe nicht gefunden', + noTasks: 'Keine Aufgaben', + showCompleted: 'Abgeschlossene anzeigen', + hideCompleted: 'Abgeschlossene ausblenden', + sortNewestFirst: 'Neueste zuerst', + sortOldestFirst: 'Älteste zuerst', + deleteConfirm: 'Aufgabe löschen', + deleteMessage: 'Sind Sie sicher, dass Sie "{name}" löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.', + }, + tags: { + createTag: 'Tag erstellen', + editTag: 'Tag bearbeiten', + name: 'Name', + namePlaceholder: 'Tag-Name', + color: 'Farbe', + preview: 'Vorschau', + tagName: 'Tag-Name', + searchPlaceholder: 'Tags suchen...', + noTagsFound: 'Keine Tags gefunden', + noTagsAssigned: 'Keine Tags zugewiesen', + manageTags: 'Verwalten', + deleteConfirm: 'Tag löschen', + deleteMessage: 'Sind Sie sicher, dass Sie "{name}" löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.', + }, + priority: { + low: 'Niedrig', + medium: 'Mittel', + high: 'Hoch', + }, + history: { + title: 'Änderungsverlauf', + show: 'Verlauf anzeigen', + hide: 'Verlauf ausblenden', + empty: 'Kein Änderungsverlauf', + changed: 'Geändert', + restore: 'Wiederherstellen', + details: 'Änderungsdetails', + completeTrue: 'Abgeschlossen', + completeFalse: 'Nicht abgeschlossen', + fields: { + note: 'Notiz', + description: 'Beschreibung', + complete: 'Abschlussstatus', + priority: 'Priorität', + list: 'Liste', + endDate: 'Fälligkeitsdatum', + startDate: 'Startdatum', + }, + }, + filters: { + title: 'Filter', + assignee: 'Zugewiesener', + selectAssignee: 'Zugewiesenen auswählen', + allUsers: 'Alle Benutzer', + reset: 'Zurücksetzen', + apply: 'Anwenden', + }, + userMenu: { + profile: 'Profil', + appearance: 'Erscheinungsbild', + light: 'Hell', + dark: 'Dunkel', + language: 'Sprache', + taskDetailView: 'Aufgabendetailansicht', + taskDetailSlideover: 'Seitenleiste', + taskDetailModal: 'Dialog', + site: 'Website', + documentation: 'Dokumentation', + github: 'GitHub-Repository', + docker: 'Docker-Images', + accountSettings: 'Kontoeinstellungen', + organizations: 'Organisationen', + analytics: 'Analytik', + timeReports: 'Zeitberichte', + switchOrganization: 'Organisation wechseln', + logout: 'Abmelden', + logoutFailed: 'Abmeldung fehlgeschlagen', + logoutFailedDescription: 'Versuchen Sie, den Browser-Cache zu leeren, um das Autorisierungstoken zu entfernen', + }, + analytics: { + page: { + title: 'Analytik', + subtitle: 'Metriken zu Produktivität und Projektgesundheit', + emptyState: 'Noch keine Daten. Erstellen Sie Aufgaben, um Analytik zu sehen.', + emptyStateForPeriod: 'Keine Daten für den ausgewählten Zeitraum. Versuchen Sie einen längeren Zeitraum.', + partialFailure: 'Einige Abschnitte konnten nicht geladen werden. Versuchen Sie es erneut.', + }, + errors: { + forbidden: 'Sie haben keinen Zugriff auf diese Analytik.', + network: 'Server nicht erreichbar. Überprüfen Sie Ihre Verbindung.', + server: 'Der Server hat einen Fehler zurückgegeben. Versuchen Sie, die Seite neu zu laden.', + unknown: 'Analytik konnte nicht geladen werden.', + }, + help: { + aria: 'Hilfe zu dieser Metrik', + }, + chartTypes: { + line: 'Linie', + bar: 'Balken', + area: 'Fläche', + stackedBar: 'Gestapelt', + stackedArea: 'Gestapelte Fläche', + horizontalBar: 'Horiz.', + donut: 'Donut', + histogram: 'Histogramm', + radar: 'Radar', + }, + units: { + days: 'T', + hours: 'Std', + }, + priorities: { + low: 'Niedrig', + medium: 'Mittel', + high: 'Hoch', + }, + filters: { + periods: { + '7d': '7 Tage', + '30d': '30 Tage', + '90d': '90 Tage', + '180d': 'Quartal', + '365d': 'Jahr', + }, + scopes: { + org: 'Gesamte Organisation', + }, + }, + drillDown: { + defaultTitle: 'Aufgaben', + empty: 'Keine Aufgaben in dieser Auswahl', + denied: 'Sie haben keine Berechtigung, Aufgabendetails einzusehen', + noTaskTitle: 'Ohne Titel', + due: 'fällig', + created: 'erstellt', + closed: 'geschlossen', + }, + sectionCard: { + noData: 'Keine Daten für den ausgewählten Zeitraum', + }, + }, + account: { + title: 'Kontoeinstellungen', + management: 'Kontoverwaltung', + deleteAccount: 'Konto löschen', + deleteConfirm: 'Sind Sie sicher, dass Sie das Konto und alle zugehörigen Daten löschen möchten?', + deleteWarning: 'Alle mit diesem Konto verbundenen Daten werden gelöscht! Diese Aktion kann nicht rückgängig gemacht werden!', + enterCode: 'Code aus E-Mail eingeben', + confirm: 'Bestätigen', + cancel: 'Abbrechen', + deleted: 'Konto gelöscht', + codeSendError: 'Code konnte nicht gesendet werden. Bitte wenden Sie sich an den Support, um Ihr Konto zu löschen.', + }, + organizations: { + title: 'Organisationen', + create: 'Organisation erstellen', + name: 'Name', + namePlaceholder: 'z. B. Mein Team', + slug: 'Slug', + slugPlaceholder: 'mein-team', + members: 'Mitglieder', + addMember: 'Mitglied hinzufügen', + email: 'E-Mail', + role: 'Rolle', + owner: 'Inhaber', + admin: 'Administrator', + member: 'Mitglied', + remove: 'Entfernen', + delete: 'Organisation löschen', + deleteConfirm: 'Sind Sie sicher, dass Sie diese Organisation und alle ihre Projekte löschen möchten?', + empty: 'Noch keine Organisationen', + currentOrg: 'Aktuelle Organisation', + active: 'Aktiv', + settings: 'Einstellungen', + general: 'Allgemein', + save: 'Speichern', + created: 'Organisation erstellt', + updated: 'Organisation aktualisiert', + deleted: 'Organisation gelöscht', + memberAdded: 'Mitglied hinzugefügt', + memberRemoved: 'Mitglied entfernt', + roleUpdated: 'Rolle aktualisiert', + close: 'Schließen', + slugTaken: 'Dieser Slug ist bereits vergeben', + }, + sso: { + noConfig: 'SSO ist für diese Organisation nicht konfiguriert', + configure: 'SSO konfigurieren', + protocol: 'Protokoll', + displayName: 'Anbietername', + displayNamePlaceholder: 'z. B. Okta, Azure AD', + emailDomain: 'E-Mail-Domain', + metadataUrl: 'IdP-Metadaten-URL', + metadataUrlRequired: 'Metadaten-URL eingeben', + metadataSynced: 'Metadaten erfolgreich synchronisiert', + metadataSyncFailed: 'Metadaten konnten nicht synchronisiert werden', + sync: 'Synchronisieren', + samlEntryPoint: 'IdP SSO-URL', + samlIssuer: 'SP Entity ID', + samlCert: 'IdP-Zertifikat', + samlCertPlaceholder: 'Fügen Sie das öffentliche IdP-Zertifikat ein (PEM-Format)', + samlCallbackUrl: 'ACS-URL (Callback)', + samlLogoutUrl: 'IdP-Logout-URL (SLO)', + requestSigning: 'Request-Signierung (Enterprise)', + requestSigningDescription: 'SAML AuthnRequests mit einem privaten Schlüssel signieren. Erforderlich bei einigen IdPs für erhöhte Sicherheit.', + generateKeysTitle: 'openssl req -x509 -newkey rsa:2048 -keyout sp-key.pem -out sp-cert.pem -days 3650 -nodes -subj "/CN=taskview"', + generateKeysHint: 'sp-key.pem → Feld Privater Schlüssel. sp-cert.pem → Feld Zertifikat + zum IdP hochladen.', + samlSigningKey: 'SP Privater Schlüssel (PEM)', + samlSigningKeyPlaceholder: 'PEM Privaten Schlüssel einfügen (-----BEGIN PRIVATE KEY-----...)', + samlSigningCert: 'SP-Zertifikat (PEM)', + samlSigningCertPlaceholder: 'PEM-Zertifikat einfügen (-----BEGIN CERTIFICATE-----...)', + secretConfigured: 'Wert ist konfiguriert (leer lassen, um aktuellen Wert beizubehalten)', + secretAlreadySet: 'Konfiguriert - leer lassen, um aktuellen Wert beizubehalten', + oidcIssuer: 'Issuer-URL', + oidcClientId: 'Client-ID', + oidcClientSecret: 'Client-Secret', + oidcCallbackUrl: 'Callback-URL', + enabled: 'Aktiviert', + disabled: 'Deaktiviert', + callbackUrlLabel: 'Callback-URL (in Ihrem IdP verwenden)', + copied: 'In die Zwischenablage kopiert', + copyFailed: 'Kopieren fehlgeschlagen', + create: 'Erstellen', + save: 'Speichern', + cancel: 'Abbrechen', + created: 'SSO-Anbieter erstellt', + updated: 'SSO-Anbieter aktualisiert', + deleted: 'SSO-Anbieter gelöscht', + domainAlreadyExists: 'SSO-Konfiguration für diese Domain existiert bereits', + saveFailed: 'SSO-Konfiguration konnte nicht gespeichert werden', + deleteFailed: 'SSO-Konfiguration konnte nicht gelöscht werden', + fillRequired: 'Bitte füllen Sie alle erforderlichen Felder aus', + }, + scim: { + description: 'Benutzer-Lebenszyklus automatisch von Ihrem IdP synchronisieren', + endpointUrl: 'SCIM-Endpoint-URL', + generateToken: 'SCIM-Token generieren', + regenerateToken: 'Token neu generieren', + tokenWarning: 'Kopieren Sie dieses Token jetzt. Es wird nicht erneut angezeigt.', + tokenGenerated: 'SCIM-Token generiert', + tokenFailed: 'Token konnte nicht generiert werden', + toggleFailed: 'SCIM konnte nicht umgeschaltet werden', + }, + apiTokens: { + title: 'API-Tokens', + description: 'Erstellen Sie Tokens, um programmgesteuert auf die API zuzugreifen.', + add: 'Neues Token generieren', + name: 'Tokenname', + namePlaceholder: 'z. B. CI/CD, Mobile App', + expiration: 'Ablauf', + noExpiration: 'Kein Ablauf', + days30: '30 Tage', + days60: '60 Tage', + days90: '90 Tage', + year1: '1 Jahr', + projects: 'Projekte', + projectsHint: 'Token auf bestimmte Projekte beschränken. Leer lassen für Zugriff auf alle Projekte.', + allProjects: 'Alle Projekte', + permissions: 'Berechtigungen', + permissionsCount: 'Berechtigungen', + permissionsDocs: 'Mehr über Berechtigungen erfahren', + generate: 'Token generieren', + tokenCreated: 'Token erstellt', + tokenDescription: 'Kopieren Sie dieses Token jetzt. Es wird nicht erneut angezeigt.', + lastUsed: 'Zuletzt verwendet', + never: 'Nie', + expires: 'Läuft ab', + deleteConfirm: 'Sind Sie sicher, dass Sie dieses Token löschen möchten? Alle Anwendungen, die es verwenden, verlieren den Zugriff.', + empty: 'Noch keine API-Tokens.', + }, + sessions: { + title: 'Aktive Sitzungen', + description: 'Verwalten Sie Ihre aktiven Sitzungen. Sie können den Zugriff für jede Sitzung außer der aktuellen widerrufen.', + current: 'Aktuelle Sitzung', + lastUsed: 'Zuletzt verwendet', + created: 'Erstellt', + deleteConfirm: 'Sind Sie sicher, dass Sie diese Sitzung beenden möchten? Das Gerät wird abgemeldet.', + deleteAll: 'Alle anderen Sitzungen beenden', + deleteAllConfirm: 'Sind Sie sicher, dass Sie alle anderen Sitzungen beenden möchten? Alle Geräte außer dem aktuellen werden abgemeldet.', + empty: 'Keine weiteren aktiven Sitzungen.', + unknown: 'Unbekanntes Gerät', + }, + notifications: { + title: 'Benachrichtigungen', + empty: 'Keine Benachrichtigungen', + markAllRead: 'Alle als gelesen markieren', + loadMore: 'Mehr laden', + settings: { + title: 'Benachrichtigungseinstellungen', + description: 'Wählen Sie aus, welche Benachrichtigungen Sie erhalten möchten und auf welche Weise.', + push: 'Push', + websocket: 'In-App', + types: { + deadline: 'Fristen', + deadlineDescription: 'Wenn eine Aufgabenfrist erreicht wird', + assign: 'Zuweisungen', + assignDescription: 'Wenn Sie einer Aufgabe zugewiesen werden', + }, + saved: 'Einstellungen gespeichert', + }, + }, + server: { + selectServer: 'Server', + addServer: 'Server hinzufügen', + addNewServer: 'Neuen Server hinzufügen', + serverUrl: 'Server-URL', + serverUrlHint: 'Geben Sie die vollständige API-Server-URL ein, z. B. https://api.beispiel.com', + defaultServer: 'Standardserver', + }, + connection: { + offline: 'Keine Internetverbindung', + restored: 'Verbindung wiederhergestellt', + reload: 'Neu laden', + }, + timeTracking: { + title: 'Zeiterfassung', + empty: 'Noch keine Zeiteinträge', + you: 'Sie', + unknownUser: 'Unbekannter Benutzer', + start: 'Start', + stop: 'Stopp', + running: 'Läuft', + addManual: 'Manuell hinzufügen', + startedAt: 'Gestartet um', + endedAt: 'Beendet um', + description: 'Beschreibung', + billable: 'Abrechenbar', + save: 'Speichern', + cancel: 'Abbrechen', + willStopOther: 'Beim Starten wird Ihr aktueller Timer für eine andere Aufgabe gestoppt', + previousStopped: 'Vorheriger Timer gestoppt', + previousStoppedDescription: 'Ihr vorheriger Timer lief {duration} und wurde gestoppt', + activeTimerTooltip: 'Klicken Sie, um die Aufgabe zu öffnen — Quadrat-Symbol zum Stoppen', + autostopHours: 'Timer automatisch stoppen nach (Stunden)', + autostopHint: 'Leer lassen zum Deaktivieren', + delete: 'Löschen', + deleteConfirmTitle: 'Zeiteintrag löschen?', + deleteConfirm: 'Diese Aktion kann nicht rückgängig gemacht werden.', + errors: { + generic: 'Zeiterfassungsaktion fehlgeschlagen', + forbidden: 'Sie haben keine Berechtigung für diese Aktion', + notFound: 'Zeiteintrag nicht gefunden', + validation: 'Ungültige Eingabedaten', + network: 'Netzwerkfehler. Überprüfen Sie Ihre Verbindung.', + }, + reports: { + title: 'Zeitberichte', + allProjects: 'Alle Projekte', + allUsers: 'Alle Benutzer', + clearUser: 'Benutzerfilter zurücksetzen', + billableOnly: 'Nur abrechenbar', + openTask: 'Aufgabe öffnen', + kpiTotal: 'Gesamtzeit', + kpiBillable: 'Abrechenbar', + kpiEntries: 'Einträge', + byTask: 'Nach Aufgabe', + byUser: 'Nach Benutzer', + byDay: 'Nach Tag', + colTask: 'Aufgabe', + colUser: 'Benutzer', + colDay: 'Tag', + colHours: 'Zeit', + colEntries: 'Einträge', + empty: 'Keine Daten für die ausgewählten Filter', + recentEntries: 'Letzte Einträge', + noPermission: 'Sie haben keine Berechtigung, Zeitberichte anzuzeigen', + noPermissionHint: 'Bitten Sie einen Projekt-Administrator um die Berechtigung zur Anzeige der Zeiterfassung, um auf Berichte zuzugreifen.', + }, + }, +} diff --git a/web/src/locales/index.ts b/web/src/locales/index.ts index 072ca88..d023e7c 100644 --- a/web/src/locales/index.ts +++ b/web/src/locales/index.ts @@ -1,11 +1,13 @@ +import de from './de' import en from './en' import ru from './ru' export const messages = { en, ru, + de, } export type Locale = keyof typeof messages -export const locales: Locale[] = ['en', 'ru'] +export const locales: Locale[] = ['en', 'ru', 'de'] export const defaultLocale: Locale = 'en'