diff --git a/docs/i18n-remaining-items.md b/docs/i18n-remaining-items.md new file mode 100644 index 0000000..c853c42 --- /dev/null +++ b/docs/i18n-remaining-items.md @@ -0,0 +1,182 @@ +# i18n — Verbleibende statische Texte + +> Stand: 2026-04-08 +> Diese Stellen verwenden noch hardcoded Strings in Object-Literalen, Arrays oder Hook-Defaults. +> Sie können nicht einfach mit `t()` gewrapped werden, da sie ausserhalb des React-Render-Kontexts definiert sind. +> **Lösung:** Array/Object in die Komponente verschieben oder eine Factory-Funktion `(t) => [...]` nutzen. + +--- + +## 1. Hook-Defaults (`useConfirm`, `usePrompt`) + +Diese Defaults propagieren in die gesamte App. Ein Fix hier wirkt global. + +| Datei | Zeile | Property | Text | +|-------|-------|----------|------| +| `hooks/useConfirm.tsx` | 26 | `title` | `'Bestätigung'` | +| `hooks/useConfirm.tsx` | 27 | `confirmLabel` | `'Bestätigen'` | +| `hooks/useConfirm.tsx` | 28 | `cancelLabel` | `'Abbrechen'` | +| `hooks/usePrompt.tsx` | 29 | `title` | `'Eingabe'` | +| `hooks/usePrompt.tsx` | 30 | `confirmLabel` | `'OK'` | +| `hooks/usePrompt.tsx` | 31 | `cancelLabel` | `'Abbrechen'` | + +--- + +## 2. Monatsnamen + +| Datei | Zeilen | Kontext | +|-------|--------|---------| +| `pages/billing/BillingDashboard.tsx` | 182–193 | Monats-Select: `'Januar'` bis `'Dezember'` (12 Einträge) | +| `components/FormGenerator/FormGeneratorReport/FormGeneratorReport.tsx` | 536–541 | Monats-Select: `'Januar'` bis `'Dezember'` (12 Einträge) | + +--- + +## 3. Tab-Labels (statische Arrays ausserhalb Komponente) + +| Datei | Zeilen | Labels | +|-------|--------|--------| +| `pages/Settings.tsx` | 23–27 | `'Profil'`, `'Darstellung'`, `'Stimme & Sprache'`, `'Neutralisierung (lokal)'`, `'Datenschutz'` | +| `pages/views/workspace/WorkspaceSettingsPage.tsx` | 16–17 | `'Generelle Einstellungen'`, `'Neutralisierung (Workspace)'` | +| `pages/views/neutralization/NeutralizationView.tsx` | 744–745 | `'Configuration'`, `'Playground'` | + +--- + +## 4. Spalten-Definitionen (Column-Arrays) + +| Datei | Zeilen | Labels | +|-------|--------|--------| +| `pages/admin/AdminLanguagesPage.tsx` | 29–32 | `'Code'`, `'Bezeichnung'`, `'Status'`, `'Einträge'` | +| `pages/admin/AdminSubscriptionsPage.tsx` | 13–23 | `'Mandant'`, `'Plan'`, `'Status'`, `'Wiederkehrend'`, `'User'`, `'Instanzen'`, `'Revenue/Mt (CHF)'`, `'Gestartet'`, `'Periodenende'`, `'Preis/User'`, `'Preis/Instanz'` | +| `pages/admin/AdminUserMandatesPage.tsx` | 104–144 | `'Benutzername'`, `'E-Mail'`, `'Vollständiger Name'`, `'Rollen'`, `'Aktiv'` | +| `pages/admin/AdminMandateRolesPage.tsx` | 106–124 | `'Bezeichnung'`, `'Beschreibung'`, `'Geltungsbereich'` | +| `pages/admin/AdminInvitationsPage.tsx` | 90–155 | `'Benutzername'`, `'E-Mail'`, `'Rollen'`, `'Gültig bis'`, `'Verwendet'`, `'Erstellt'` | +| `pages/admin/AdminFeatureRolesPage.tsx` | 138–155 | `'Rollen-Label'`, `'Beschreibung'`, `'Feature'` | +| `pages/admin/AdminFeatureInstanceUsersPage.tsx` | 205–245 | `'Benutzername'`, `'E-Mail'`, `'Vollständiger Name'`, `'Rollen'`, `'Aktiv'` | +| `pages/admin/AdminFeatureAccessPage.tsx` | 91–104 | `'Name'`, `'Feature'`, `'Aktiv'` | +| `pages/views/graphicalEditor/GraphicalEditorWorkflowsPage.tsx` | 184–235 | `'Workflow'`, `'Aktiv'`, `'Läuft'`, `'Steht bei'`, `'Erstellt'`, `'Zuletzt gestartet'`, `'Läufe'` | +| `pages/views/graphicalEditor/GraphicalEditorTemplatesPage.tsx` | 174–202 | `'Vorlage'`, `'Scope'`, `'Freigegeben'`, `'Erstellt von'`, `'Erstellt'` | + +--- + +## 5. Formular-Feld-Definitionen (AttributeDefinition-Arrays) + +| Datei | Zeilen | Labels | +|-------|--------|--------| +| `pages/Settings.tsx` | 56–58 | `'Vollstaendiger Name'`, `'E-Mail-Adresse'`, `'Sprache'` + descriptions + placeholders | +| `pages/admin/wizards/FeatureInstanceWizard.tsx` | 75–78 | `'Mandant'`, `'Feature'`, `'Bezeichnung'`, `'Aktiv'` | +| `pages/admin/InstanceDetailModal.tsx` | 186–279 | `'Benutzer'`, `'Rollen'`, `'Aktiv'`, `'Einstellungen'`, `'Bezeichnung'`, `'Aktiviert'` | +| `pages/admin/AdminMandateRolesPage.tsx` | 165–171 | `'Geltungsbereich'`, `'Nur dieser Mandant'`, `'Template (wird bei neuen Mandanten kopiert)'` | +| `pages/admin/AdminMandateRolePermissionsPage.tsx` | 219–221 | `'Mandanten-Rollen'`, `'Alle (inkl. Templates)'`, `'Nur Templates'` | +| `pages/admin/AdminFeatureRolesPage.tsx` | 173–205 | `'Rollen-Label'`, `'Beschreibung'` + descriptions | +| `pages/admin/AdminFeatureInstanceUsersPage.tsx` | 272–299 | `'Benutzer'`, `'Rollen'`, `'Aktiv'` | +| `pages/admin/AdminInvitationsPage.tsx` | 181 | `'Gültigkeitsdauer (Stunden)'` | +| `pages/admin/AdminFeatureAccessPage.tsx` | 629–636 | `'Bezeichnung'`, `'Aktiviert'` | + +--- + +## 6. Status-/Option-Maps (Object-Literale) + +| Datei | Zeilen | Kontext | +|-------|--------|---------| +| `pages/billing/SubscriptionTab.tsx` | 48–53 | Status-Map: `'Zahlung ausstehend'`, `'Geplant'`, `'Aktiv'`, `'Testphase'`, `'Abgelaufen'` | +| `components/FlowEditor/editor/CanvasHeader.tsx` | 40–42 | Status-Map: `'Entwurf'`, `'Veröffentlicht'`, `'Archiviert'` | +| `components/FlowEditor/editor/WorkflowConfigurationModal.tsx` | 17–20 | Trigger-Typen: `'Manueller Trigger'`, `'Formular'`, `'Zeitplan'`, `'Immer aktiv'` | +| `components/FlowEditor/nodes/start/ScheduleStartNodeConfig.tsx` | 22–49 | Schedule-Optionen: `'Täglich'`, `'Werktage'`, `'Bestimmte Tage'`, `'Intervall'`, `'Sekunden'`, `'Minuten'`, `'Stunden'`, `'Tage'`, `'Jahre'` | +| `components/RbacExportImport/RbacExportImport.tsx` | 49–62 | Import-Modi: `'Zusammenführen'`, `'Nur hinzufügen'`, `'Ersetzen'` + descriptions | +| `components/AccessRules/AccessRulesEditor.tsx` | 633–636 | Tab-Labels: `'Daten'`, `'Ressourcen'` | +| `hooks/useAccessRules.tsx` | 23–26 | Scope-Labels: `'Keine'`, `'Eigene'`, `'Gruppe'`, `'Alle'` | + +--- + +## 7. Action-Button `title:`-Props (in Object-Literalen) + +| Datei | Zeilen | Titles | +|-------|--------|--------| +| `pages/admin/AdminUsersPage.tsx` | 200–212 | `'Bearbeiten'`, `'Löschen'`, `'Passwort-Link senden'` | +| `pages/admin/AdminUserMandatesPage.tsx` | 352–356 | `'Rollen bearbeiten'`, `'Aus Mandant entfernen'` | +| `pages/admin/AdminMandatesPage.tsx` | 127–234 | `'Mandant deaktivieren'`, `'Deaktivieren'`, `'Hard Delete (irreversibel)'`, `'Endgültig löschen'`, `'Bearbeiten'`, `'Deaktivieren (Soft-Delete)'` | +| `pages/admin/AdminMandateRolesPage.tsx` | 430–435 | `'Rolle bearbeiten'`, `'Rolle löschen'` | +| `pages/admin/AdminInvitationsPage.tsx` | 354–362 | `'Einladung widerrufen'`, `'Einladungs-Link anzeigen'` | +| `pages/admin/AdminFeatureRolesPage.tsx` | 372–384 | `'Rolle bearbeiten'`, `'Rolle löschen'`, `'Berechtigungen verwalten'` | +| `pages/admin/AdminFeatureInstanceUsersPage.tsx` | 535–539 | `'Rollen bearbeiten'`, `'Aus Instanz entfernen'` | +| `pages/admin/AdminFeatureAccessPage.tsx` | 457–471 | `'Instanz löschen'`, `'Instanz bearbeiten'`, `'Rollen synchronisieren'` | +| `pages/admin/PermissionMatrix.tsx` | 39 | `'Benutzer entfernen'` | +| `pages/basedata/ConnectionsPage.tsx` | 324–347 | `'Bearbeiten'`, `'Löschen'`, `'Verbinden'`, `'Token erneuern'` | +| `pages/basedata/FilesPage.tsx` | 232–458 | `'Neuer Ordner'`, `'Bearbeiten'`, `'Löschen'`, `'Herunterladen'`, `'Vorschau'` | +| `pages/basedata/PromptsPage.tsx` | 215–225 | `'Duplizieren'`, `'Bearbeiten'`, `'Löschen'` | +| `pages/billing/AdminSubscriptionsPage.tsx` | 67 | `'Sofort kündigen'` | +| `pages/views/trustee/TrusteePositionsView.tsx` | 455–467 | `'Bearbeiten'`, `'Löschen'`, `'In Buchhaltung synchronisieren'` | +| `pages/views/trustee/TrusteePositionDocumentsView.tsx` | 192–198 | `'Verknüpfung bearbeiten'`, `'Verknüpfung entfernen'` | +| `pages/views/trustee/TrusteeDocumentsView.tsx` | 225–238 | `'Bearbeiten'`, `'Löschen'`, `'Herunterladen'` | +| `pages/views/realestate/RealEstateProjectsView.tsx` | 167–168 | `'Bearbeiten'`, `'Löschen'` | +| `pages/views/realestate/RealEstateParcelsView.tsx` | 186–194 | `'Bearbeiten'`, `'Löschen'` | +| `pages/views/graphicalEditor/GraphicalEditorWorkflowsPage.tsx` | 136–336 | `'Workflow umbenennen'`, `'Bearbeiten'`, `'Löschen'`, `'Umbenennen'`, `'Aktivieren'`, `'Deaktivieren'`, `'Ausführen'` | +| `pages/views/graphicalEditor/GraphicalEditorTemplatesPage.tsx` | 149–289 | `'Vorlage umbenennen'`, `'Im Editor öffnen'`, `'Löschen'`, `'Umbenennen'`, `'Als Workflow kopieren'`, `'Scope ändern'` | +| `pages/views/chatbot/ChatbotConversationsView.tsx` | 88 | `'Konversation löschen'` | +| `components/FlowEditor/editor/Automation2FlowEditor.tsx` | 239 | `'Workflow speichern'` | +| `components/FolderTree/FolderTree.tsx` | 384, 768 | `'Neuer Ordner'` (prompt title) | + +--- + +## 8. Onboarding-Texte (Object-Literale) + +| Datei | Zeilen | Labels | +|-------|--------|--------| +| `components/OnboardingAssistant.tsx` | 99–149 | `'Mandant einrichten'`, `'Erstes Feature aktivieren'`, `'Erste Datenquelle einbinden'`, `'Ersten AI-Chat starten'` | + +--- + +## 9. ClickUp Node Config (Feld-Optionen) + +| Datei | Zeilen | Labels | +|-------|--------|--------| +| `components/FlowEditor/nodes/configs/ClickUpNodeConfig.tsx` | 786–794 | `'Titel (name)'`, `'Beschreibung'`, `'Status'`, `'Priorität (1–4)'`, `'Fälligkeit (Datum oder ms)'`, `'Zeitschätzung (Stunden)'`, `'Zeitschätzung (ms)'`, `'Zugewiesene'`, `'Benutzerdefiniertes Feld'` | + +--- + +## 10. Sonstige Einzel-Stellen + +| Datei | Zeile | Property | Text | +|-------|-------|----------|------| +| `pages/admin/ChatbotConfigSection.tsx` | 58 | `label` | `'Althaus Preprocessor'` | +| `pages/views/trustee/TrusteePositionsView.tsx` | 167 | `label` | `'Belege'` | +| `pages/views/trustee/TrusteePositionsView.tsx` | 232 | `label` | `'Sync-Status'` | +| `pages/views/trustee/TrusteePositionsView.tsx` | 445 | `label` | `'Buchhaltung synchronisieren'` | +| `pages/views/trustee/TrusteeExpenseImportView.tsx` | 361 | `label` | `'Daily at 22:00'` | +| `pages/basedata/PromptsPage.tsx` | 81 | `label` | `'Created By'` | +| `pages/basedata/FilesPage.tsx` | 152 | `label` | `'Created By'` | +| `components/FlowEditor/nodes/start/FormStartNodeConfig.tsx` | 22 | `label` | `'Feld 1'` | +| `components/FlowEditor/nodes/start/FormStartNodeConfig.tsx` | 116 | `label` | `'Neues Feld'` | + +--- + +## 11. Sprach-/Locale-Listen (Eigenname-Labels — evtl. NICHT übersetzen) + +> Diese Listen enthalten Sprachnamen in der jeweiligen Sprache (Endonym). Sie werden typischerweise **nicht** übersetzt, da der User die Sprache in ihrer Originalbezeichnung erkennen soll. + +| Datei | Zeilen | Kontext | +|-------|--------|---------| +| `pages/Settings.tsx` | 50–52, 563–565 | Fallback-Sprachoptionen: `'Deutsch'`, `'English'`, `'Français'` | +| `pages/views/workspace/WorkspaceInput.tsx` | 16–27 | STT-Sprachliste (12 Sprachen) | +| `pages/admin/AdminLanguagesPage.tsx` | 38–65 | Alle verfügbaren Sprach-Codes mit Endonymen | +| `components/UiComponents/VoiceLanguageSelect/VoiceLanguageSelect.tsx` | 23–32 | Voice-Sprachliste mit Endonymen | +| `components/FormGenerator/FormGeneratorForm/FormGeneratorForm.tsx` | 672–675 | Fallback-Sprachoptionen | + +--- + +## Zusammenfassung + +| Kategorie | Anzahl Stellen | Dateien | +|-----------|---------------|---------| +| Hook-Defaults | 6 | 2 | +| Monatsnamen | 24 | 2 | +| Tab-Labels | 9 | 3 | +| Spalten-Definitionen | ~55 | 10 | +| Formular-Felder | ~30 | 9 | +| Status-/Option-Maps | ~30 | 7 | +| Action-Button titles | ~65 | 23 | +| Onboarding-Texte | 4 | 1 | +| ClickUp-Felder | 9 | 1 | +| Sonstige | 9 | 5 | +| Sprach-Listen (evtl. nicht übersetzen) | ~60 | 5 | +| **Total (ohne Sprach-Listen)** | **~241** | **~45 Dateien** | diff --git a/scripts/list_t_errors.py b/scripts/list_t_errors.py new file mode 100644 index 0000000..60a8b34 --- /dev/null +++ b/scripts/list_t_errors.py @@ -0,0 +1,17 @@ +import re +from pathlib import Path + +text = Path(__file__).resolve().parent.parent / "tsc-out.txt" +content = text.read_text(encoding="utf-8") +files = sorted( + { + m.group(1) + for line in content.splitlines() + if "Cannot find name 't'" in line + for m in [re.match(r"^(src/[^\(:]+\.tsx)", line)] + if m + } +) +for f in files: + print(f) +print("TOTAL", len(files), file=__import__("sys").stderr) diff --git a/src/components/AccessRules/AccessLevelSelect.tsx b/src/components/AccessRules/AccessLevelSelect.tsx index bafba16..cada42e 100644 --- a/src/components/AccessRules/AccessLevelSelect.tsx +++ b/src/components/AccessRules/AccessLevelSelect.tsx @@ -5,7 +5,8 @@ */ import React from 'react'; -import { ACCESS_LEVEL_OPTIONS, type AccessLevel, getAccessLevelColor } from '../../hooks/useAccessRules'; +import { _getAccessLevelOptions, type AccessLevel, getAccessLevelColor } from '../../hooks/useAccessRules'; +import { useLanguage } from '../../providers/language/LanguageContext'; import styles from './AccessRules.module.css'; interface AccessLevelSelectProps { @@ -25,6 +26,8 @@ export const AccessLevelSelect: React.FC = ({ showLabel = false, compact = false, }) => { + const { t } = useLanguage(); + const accessLevelOptions = _getAccessLevelOptions(t); const currentColor = getAccessLevelColor(value); return ( @@ -42,7 +45,7 @@ export const AccessLevelSelect: React.FC = ({ color: currentColor, }} > - {ACCESS_LEVEL_OPTIONS.map(option => ( + {accessLevelOptions.map(option => (