diff --git a/README.md b/README.md index e41b873..cb652b8 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,21 @@ This is the standalone dockerized web application for the TUBCO onboarding and o 5. Open test mailbox: - `http://localhost:8025` +## Translations +This project now uses Django's standard i18n workflow for long-term maintainability. + +- Extract/update message catalogs: + - `docker compose exec -T web django-admin makemessages -l en` +- Compile translations: + - `docker compose exec -T web django-admin compilemessages` +- Add more languages the same way: + - `docker compose exec -T web django-admin makemessages -l de` + +Notes: +- `gettext` is installed in the Docker image, so `compilemessages` works inside the container. +- Translation files live under `backend/locale/`. +- Core fixed UI is bilingual now; dynamic builder content and most PDF/email business text are not fully bilingual yet. + ## Current implemented scope - Onboarding form with labels mapped from your CSV schema. - Stores requests in PostgreSQL. diff --git a/backend/Dockerfile b/backend/Dockerfile index 46136ee..9091816 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,7 +6,7 @@ ENV PYTHONUNBUFFERED=1 WORKDIR /app RUN apt-get update \ - && apt-get install -y --no-install-recommends build-essential netcat-openbsd \ + && apt-get install -y --no-install-recommends build-essential netcat-openbsd gettext \ && rm -rf /var/lib/apt/lists/* RUN groupadd -g 1000 app && useradd -u 1000 -g app -m app diff --git a/backend/config/settings.py b/backend/config/settings.py index cd7ddd9..45a9181 100644 --- a/backend/config/settings.py +++ b/backend/config/settings.py @@ -38,6 +38,7 @@ INSTALLED_APPS = [ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -83,7 +84,12 @@ AUTH_PASSWORD_VALIDATORS = [ {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}, ] -LANGUAGE_CODE = 'de-de' +LANGUAGE_CODE = os.getenv('DJANGO_LANGUAGE_CODE', 'de') +LANGUAGES = [ + ('de', 'Deutsch'), + ('en', 'English'), +] +LOCALE_PATHS = [BASE_DIR / 'locale'] TIME_ZONE = 'Europe/Berlin' USE_I18N = True USE_TZ = True diff --git a/backend/config/urls.py b/backend/config/urls.py index 899547b..a6b96bc 100644 --- a/backend/config/urls.py +++ b/backend/config/urls.py @@ -5,6 +5,7 @@ from django.urls import include, path urlpatterns = [ path('admin/', admin.site.urls), + path('i18n/', include('django.conf.urls.i18n')), path('accounts/', include('django.contrib.auth.urls')), path('', include('workflows.urls')), ] diff --git a/backend/locale/en/LC_MESSAGES/django.mo b/backend/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 0000000..031e539 Binary files /dev/null and b/backend/locale/en/LC_MESSAGES/django.mo differ diff --git a/backend/locale/en/LC_MESSAGES/django.po b/backend/locale/en/LC_MESSAGES/django.po new file mode 100644 index 0000000..684bf9c --- /dev/null +++ b/backend/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,403 @@ +msgid "" +msgstr "" +"Project-Id-Version: tubco-portal\n" +"POT-Creation-Date: 2026-03-24 00:00+0000\n" +"PO-Revision-Date: 2026-03-24 00:00+0000\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "%(count)s Auswahl(en) konnten nicht verarbeitet werden." +msgstr "%(count)s selection(s) could not be processed." + +msgid "%(count)s Eintrag/Einträge gelöscht." +msgstr "%(count)s entry/entries deleted." + +msgid "%(count)s Einträge sichtbar" +msgstr "%(count)s entries visible" + +msgid "14 Tage" +msgstr "14 days" + +msgid "Abmelden" +msgstr "Log out" + +msgid "Abschluss" +msgstr "Finish" + +msgid "Admin" +msgstr "Admin" + +msgid "Admin Apps" +msgstr "Admin Apps" + +msgid "Aktion" +msgstr "Action" + +msgid "Aktivität 14 Tage" +msgstr "Activity 14 Days" + +msgid "Aktivitätsverlauf" +msgstr "Activity Timeline" + +msgid "Alle Vorgänge, durchsuchbar und mit Dokumenten verknüpft." +msgstr "All requests, searchable and linked with documents." + +msgid "Alle erfassten Onboarding-Vorgänge im aktuellen System." +msgstr "All onboarding requests captured in the current system." + +msgid "Anfrage gespeichert" +msgstr "Request saved" + +msgid "Anfragen Dashboard" +msgstr "Requests Dashboard" + +msgid "Anmelden" +msgstr "Sign in" + +msgid "Anmeldung" +msgstr "Sign in" + +msgid "Anmeldung fehlgeschlagen. Bitte Zugangsdaten prüfen." +msgstr "Login failed. Please check your credentials." + +msgid "Apps" +msgstr "Apps" + +msgid "Austritte und Rückgaben in derselben Prozessübersicht." +msgstr "Departures and returns in the same process overview." + +msgid "Auswahl löschen" +msgstr "Delete selection" + +msgid "Beschäftigung und Termine" +msgstr "Employment and dates" + +msgid "Bitte melden Sie sich mit Ihrem Benutzerkonto an." +msgstr "Please sign in with your user account." + +msgid "Bitte prüfen Sie die markierten Felder. Ungültige Eingaben wurden erkannt." +msgstr "Please check the highlighted fields. Invalid input was detected." + +msgid "Checklistenpunkte für das Einweisungsprotokoll konfigurieren." +msgstr "Configure checklist items for the introduction protocol." + +msgid "Dashboard öffnen" +msgstr "Open dashboard" + +msgid "Datensätze können direkt in der Tabelle gefiltert, geöffnet, geprüft oder gelöscht werden." +msgstr "Records can be filtered, opened, checked, or deleted directly in the table." + +msgid "Die letzten 14 Tage in einer kompakten Ansicht über alle Onboarding- und Offboarding-Vorgänge." +msgstr "The last 14 days in a compact view across all onboarding and offboarding requests." + +msgid "Django Admin" +msgstr "Django Admin" + +msgid "Dokument" +msgstr "Document" + +msgid "Dokumentation, Architektur und Runbook." +msgstr "Documentation, architecture, and runbook." + +msgid "Dokumente, Status und Einweisungsaktionen in einer verdichteten Arbeitsansicht." +msgstr "Documents, status, and introduction actions in a condensed work view." + +msgid "E-Mail" +msgstr "Email" + +msgid "E-Mail Routing" +msgstr "Email routing" + +msgid "E-Mail:" +msgstr "Email:" + +msgid "Einweisung" +msgstr "Introduction" + +msgid "Einweisung wurde als Entwurf gespeichert." +msgstr "Introduction was saved as draft." + +msgid "Einweisung wurde als abgeschlossen gespeichert." +msgstr "Introduction was saved as completed." + +msgid "Einweisung wurde zurückgesetzt." +msgstr "Introduction was reset." + +msgid "Einweisung öffnen" +msgstr "Open introduction" + +msgid "Einweisungs- und Übergabeprotokoll wurde erzeugt." +msgstr "Introduction and handover protocol was generated." + +msgid "Einweisungs-Builder" +msgstr "Introduction Builder" + +msgid "Einweisungsprotokoll aus Live-Status wurde erzeugt." +msgstr "Introduction protocol from live status was generated." + +msgid "Erstellt" +msgstr "Created" + +msgid "Fast geschafft. Bitte Abschlussdaten prüfen und die Anfrage absenden." +msgstr "Almost done. Please review the final details and submit the request." + +msgid "Felder, Schritte und Optionen verwalten." +msgstr "Manage fields, steps, and options." + +msgid "Form Builder" +msgstr "Form Builder" + +msgid "Geplante Welcome Mails verwalten." +msgstr "Manage scheduled welcome emails." + +msgid "Geräte, Software und Zugänge" +msgstr "Devices, software, and access" + +msgid "Gesamtbestand" +msgstr "Total records" + +msgid "Hardware-Liste" +msgstr "Hardware list" + +msgid "IT-Rückgabe" +msgstr "IT return" + +msgid "IT-Setup" +msgstr "IT setup" + +msgid "Integrationen" +msgstr "Integrations" + +msgid "Keine Einträge ausgewählt." +msgstr "No entries selected." + +msgid "Keine konfigurierten Felder in diesem Schritt." +msgstr "No configured fields in this step." + +msgid "Keine passenden Einträge gefunden." +msgstr "No matching entries found." + +msgid "Konfiguration, Tests und Steuerung." +msgstr "Configuration, tests, and controls." + +msgid "Live-Protokoll" +msgstr "Live protocol" + +msgid "Live-Protokoll öffnen" +msgstr "Open live protocol" + +msgid "Löschen" +msgstr "Delete" + +msgid "Mehrschritt-Formular" +msgstr "Multi-step form" + +msgid "Mehrseitiges Formular mit konfigurierbaren Feldern aus dem Admin." +msgstr "Multi-page form with configurable fields from the admin." + +msgid "Mitarbeitende suchen (Name oder E-Mail)" +msgstr "Search employees (name or email)" + +msgid "Mitarbeitende suchen, Daten vorbefüllen, Offboarding-Dokumente erzeugen und Rückgabe-Prozess starten." +msgstr "Search employees, prefill data, generate offboarding documents, and start the return process." + +msgid "Mitarbeiter" +msgstr "Staff" + +msgid "Nach Name oder E-Mail suchen" +msgstr "Search by name or email" + +msgid "Neu erzeugen" +msgstr "Regenerate" + +msgid "Neue Mitarbeitende erfassen, PDF mit Briefkopf erstellen, Benachrichtigungen senden und in Nextcloud ablegen." +msgstr "Capture new employees, generate a PDF with letterhead, send notifications, and store it in Nextcloud." + +msgid "Nextcloud- und E-Mail-Setup." +msgstr "Nextcloud and email setup." + +msgid "Nextcloud:" +msgstr "Nextcloud:" + +msgid "Nicht relevant" +msgstr "Not relevant" + +msgid "Noch keine Vorgänge vorhanden." +msgstr "No requests available yet." + +msgid "Noch nicht verfügbar" +msgstr "Not available yet" + +msgid "Notizen und Freigabe" +msgstr "Notes and approval" + +msgid "Offboarding" +msgstr "Offboarding" + +msgid "Offboarding starten" +msgstr "Start offboarding" + +msgid "Offboarding wurde erfolgreich gespeichert (ID: %(request_id)s). Das PDF wird im Hintergrund erzeugt." +msgstr "Offboarding was saved successfully (ID: %(request_id)s). The PDF is being generated in the background." + +msgid "Offboarding-Anfrage" +msgstr "Offboarding request" + +msgid "Offboarding-Anfrage speichern" +msgstr "Save offboarding request" + +msgid "Onboarding" +msgstr "Onboarding" + +msgid "Onboarding + Offboarding" +msgstr "Onboarding + Offboarding" + +msgid "Onboarding starten" +msgstr "Start onboarding" + +msgid "Onboarding wurde erfolgreich gespeichert (ID: %(request_id)s). Das PDF wird im Hintergrund erzeugt." +msgstr "Onboarding was saved successfully (ID: %(request_id)s). The PDF is being generated in the background." + +msgid "Onboarding-Anfrage" +msgstr "Onboarding request" + +msgid "Onboarding-Anfrage absenden" +msgstr "Submit onboarding request" + +msgid "Operations Console" +msgstr "Operations Console" + +msgid "PDF + E-Mail Workflow bereit" +msgstr "PDF + Email Workflow Ready" + +msgid "PDF Zugriff" +msgstr "PDF access" + +msgid "PDF erzeugen" +msgstr "Generate PDF" + +msgid "PDF öffnen" +msgstr "Open PDF" + +msgid "PDFs + Live-Protokolle" +msgstr "PDFs + live protocols" + +msgid "Person" +msgstr "Person" + +msgid "Person, Rolle, Abteilung" +msgstr "Person, role, department" + +msgid "Produktion" +msgstr "Production" + +msgid "Profile-Suche" +msgstr "Profile search" + +msgid "Projekt Wiki" +msgstr "Project Wiki" + +msgid "Rolle:" +msgstr "Role:" + +msgid "Schließen" +msgstr "Close" + +msgid "Sie haben keine Berechtigung für diese Aktion." +msgstr "You do not have permission for this action." + +msgid "Stammdaten" +msgstr "Master data" + +msgid "Standard-Einweisungs-PDF" +msgstr "Standard introduction PDF" + +msgid "Standard-PDF öffnen" +msgstr "Open standard PDF" + +msgid "Status" +msgstr "Status" + +msgid "Status, Suchfunktion, PDF-Links und Verlauf aller Onboarding-/Offboarding-Anfragen." +msgstr "Status, search, PDF links, and history of all onboarding/offboarding requests." + +msgid "Status:" +msgstr "Status:" + +msgid "Steuert Onboarding- und Offboarding-Prozesse an einem Ort. Die Oberfläche priorisiert Kennzahlen, Aktivität und direkte Aktionen in der Vorgangsliste." +msgstr "Controls onboarding and offboarding processes in one place. The interface prioritizes metrics, activity, and direct actions in the request list." + +msgid "Suche" +msgstr "Search" + +msgid "Suche + Bulk-Aktionen" +msgstr "Search + bulk actions" + +msgid "Suchen" +msgstr "Search" + +msgid "TUBCO Onboarding & Offboarding Portal" +msgstr "TUBCO Onboarding & Offboarding Portal" + +msgid "Testmodus" +msgstr "Test mode" + +msgid "Tipp: Die letzten Vorgänge sehen Sie jederzeit im Anfragen Dashboard." +msgstr "Tip: You can always see the latest requests in the Requests Dashboard." + +msgid "Typ" +msgstr "Type" + +msgid "Vertrag" +msgstr "Contract" + +msgid "Vollständige Datenverwaltung." +msgstr "Full data management." + +msgid "Vorbefüllt aus:" +msgstr "Prefilled from:" + +msgid "Vorgänge" +msgstr "Requests" + +msgid "Weiter" +msgstr "Next" + +msgid "Welcome E-Mails" +msgstr "Welcome Emails" + +msgid "Wählen Sie den gewünschten Prozess." +msgstr "Choose the desired process." + +msgid "Zeitraum des visuellen Aktivitätsverlaufs in dieser Übersicht." +msgstr "Time span of the visual activity timeline in this overview." + +msgid "Zentrale Arbeitsfläche für Anfragen, PDF-Generierung, E-Mail-Workflows und Ablage in Nextcloud." +msgstr "Central workspace for requests, PDF generation, email workflows, and storage in Nextcloud." + +msgid "Zur Startseite" +msgstr "Back to home" + +msgid "Zurück" +msgstr "Back" + +msgid "Zurücksetzen" +msgstr "Reset" + +msgid "aktiv" +msgstr "active" + +msgid "ausgewählt" +msgstr "selected" + +msgid "inaktiv" +msgstr "inactive" + +msgid "z. B. max.mustermann@tub.co" +msgstr "e.g. john.doe@tub.co" + +msgid "Öffnen" +msgstr "Open" + diff --git a/backend/workflows/templates/registration/login.html b/backend/workflows/templates/registration/login.html index bd50514..df54158 100644 --- a/backend/workflows/templates/registration/login.html +++ b/backend/workflows/templates/registration/login.html @@ -1,10 +1,11 @@ -{% load static %} +{% load static i18n %} +{% get_current_language as CURRENT_LANGUAGE %} - +
-Bitte melden Sie sich mit Ihrem Benutzerkonto an.
+{% trans "Bitte melden Sie sich mit Ihrem Benutzerkonto an." %}