diff --git a/.gitignore b/.gitignore index 36bc7572f..b642776ca 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,5 @@ tunnel.log .develop.env **/result **/result-* -.develop.cmd \ No newline at end of file +.develop.cmd +/.vscode \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index feb13d0da..2668fd3ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,41 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [27.4.11](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.10...v27.4.11) (2023-06-20) + + +### Bug Fixes + +* **course:** fix [#28](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/28) by allowing course deletion with inactive participants only ([9dfd91b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/9dfd91b2f864424cf940259890afb8bf8cb0fdcf)) +* **letter:** renewal reminder and renewal idents switched ([064b984](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/064b984945288172c094485d8d3622d196333e0e)) + +## [27.4.10](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.9...v27.4.10) (2023-06-19) + + +### Bug Fixes + +* **lint:** remove redundant parenthesis ([4956e6b](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/4956e6bf57458a5e76efc582f6127b84a055c4de)) +* **test:** resepct uniqueness for ldap primary keys ([d1badf1](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d1badf16fc9c45ee547ec1e3fe677e16645683f0)) +* **test:** resepect uniqueness for ldap, 2nd attempt ([d06448a](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/d06448a4a8c194368c077d5ca7bf8d0feca86d60)) + +## [27.4.9](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.8...v27.4.9) (2023-06-07) + +## [27.4.8](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.7...v27.4.8) (2023-06-03) + + +### Bug Fixes + +* **qualification:** prevent qualification mixups ([88d4356](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/88d43560ae8de1480502914d9c95d6376a3c68cc)) +* **tutorial:** template moving works now ([b982e59](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/b982e59b630fbdb3fe8f37c979de8e8726b78ea9)) + +## [27.4.7](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.6...v27.4.7) (2023-05-29) + + +### Bug Fixes + +* **build:** linter complains ([ac57b1c](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/ac57b1cd32909c8314f3a3b15431d280911af643)) +* **qualifications:** fix [#78](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/issues/78) block/unblock no longer deletes company association ([3cb66c6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/commit/3cb66c6211b9f15127d88f448557acb4a3a2dd5c)) + ## [27.4.6](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.5...v27.4.6) (2023-05-24) ## [27.4.5](https://gitlab2.rz.ifi.lmu.de/uni2work/uni2work/compare/v27.4.4...v27.4.5) (2023-05-23) diff --git a/messages/faq/de-de-formal.msg b/messages/faq/de-de-formal.msg index 75427b0e1..221b1f5b1 100644 --- a/messages/faq/de-de-formal.msg +++ b/messages/faq/de-de-formal.msg @@ -5,7 +5,7 @@ FAQNoCampusAccount: Ich habe keine Fraport AG Kennung (Büko-Login); kann ich trotzdem Zugang zum System erhalten? FAQForgottenPassword: Ich habe mein Passwort vergessen FAQCampusCantLogin: Ich kann mich mit meiner Fraport AG Kennung (Büko-Login) nicht anmelden -FAQCourseCorrectorsTutors: Wie kann ich Tutoren oder Korrektoren für meinen Kurs konfigurieren? -FAQNotLecturerHowToCreateCourses: Wie kann ich einen neuen Kurs anlegen? +FAQCourseCorrectorsTutors: Wie kann ich Ausbilder oder Korrektoren für meine Kursart konfigurieren? +FAQNotLecturerHowToCreateCourses: Wie kann ich eine neue Kursart anlegen? FAQExamPoints: Warum kann ich bei meiner Klausur keine Punkte eintragen? FAQInvalidCredentialsAdAccountDisabled: Ich kann mich nicht anmelden und bekomme die Meldung „Benutzereintrag gesperrt“ \ No newline at end of file diff --git a/messages/faq/en-eu.msg b/messages/faq/en-eu.msg index 2f40802c9..0686713bb 100644 --- a/messages/faq/en-eu.msg +++ b/messages/faq/en-eu.msg @@ -5,7 +5,7 @@ FAQNoCampusAccount: I don't have Fraport AG credentials (Büko login); can I still get access? FAQForgottenPassword: I have forgotten my password FAQCampusCantLogin: I can't log in using my Fraport AG credentials (Büko login) -FAQCourseCorrectorsTutors: How can I add tutors or correctors to my course? +FAQCourseCorrectorsTutors: How can I add instructors or correctors to my course? FAQNotLecturerHowToCreateCourses: How can I create new courses? FAQExamPoints: Why can't I enter achievements for my exam as points? FAQInvalidCredentialsAdAccountDisabled: I can't log in and am instead given the message “Account disabled” \ No newline at end of file diff --git a/messages/uniworx/categories/I18n/de-de-formal.msg b/messages/uniworx/categories/I18n/de-de-formal.msg index ecc004305..1846165d1 100644 --- a/messages/uniworx/categories/I18n/de-de-formal.msg +++ b/messages/uniworx/categories/I18n/de-de-formal.msg @@ -3,8 +3,8 @@ # SPDX-License-Identifier: AGPL-3.0-or-later CorByProportionOnly proportion@Rational: #{rationalToFixed3 proportion} Anteile -CorByProportionIncludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile - Tutorium -CorByProportionExcludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile + Tutorium +CorByProportionIncludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile - Kurs +CorByProportionExcludingTutorial proportion@Rational: #{rationalToFixed3 proportion} Anteile + Kurs ExamPassed: Bestanden ExamNotPassed: Nicht bestanden I18nExamResultNoShow: Nicht erschienen diff --git a/messages/uniworx/categories/I18n/en-eu.msg b/messages/uniworx/categories/I18n/en-eu.msg index 56b27b0ac..5aba18835 100644 --- a/messages/uniworx/categories/I18n/en-eu.msg +++ b/messages/uniworx/categories/I18n/en-eu.msg @@ -3,8 +3,8 @@ # SPDX-License-Identifier: AGPL-3.0-or-later CorByProportionOnly proportion: #{rationalToFixed3 proportion} parts -CorByProportionIncludingTutorial proportion: #{rationalToFixed3 proportion} parts - tutorials -CorByProportionExcludingTutorial proportion: #{rationalToFixed3 proportion} parts + tutorials +CorByProportionIncludingTutorial proportion: #{rationalToFixed3 proportion} parts - courses +CorByProportionExcludingTutorial proportion: #{rationalToFixed3 proportion} parts + courses ExamPassed: Passed ExamNotPassed: Failed I18nExamResultNoShow: Not present diff --git a/messages/uniworx/categories/authorization/de-de-formal.msg b/messages/uniworx/categories/authorization/de-de-formal.msg index b7ee11560..0c8732515 100644 --- a/messages/uniworx/categories/authorization/de-de-formal.msg +++ b/messages/uniworx/categories/authorization/de-de-formal.msg @@ -21,16 +21,16 @@ UnauthorizedTokenInvalidImpersonation: Ihr Authorisierungs-Token enthält die An UnauthorizedToken404: Authorisierungs-Tokens können nicht auf Fehlerseiten ausgewertet werden. UnauthorizedSupervisor: Sie sind kein Ansprechpartner:in für diesen Benutzer:in. UnauthorizedSiteAdmin: Sie sind nicht System-weiter Administrator:in. -UnauthorizedSchoolAdmin: Sie sind nicht als Administrator:in für dieses Institut eingetragen. -UnauthorizedAdminEscalation: Sie sind nicht Administrator:in für alle Institute, für die dieser Nutzer/diese Nutzerin Administrator:in oder Veranstalter:in ist. +UnauthorizedSchoolAdmin: Sie sind nicht als Administrator:in für diesen Bereich eingetragen. +UnauthorizedAdminEscalation: Sie sind nicht Administrator:in für alle Bereiche, für die dieser Nutzer/diese Nutzerin Administrator:in oder Veranstalter:in ist. UnauthorizedExamOffice: Sie sind nicht mit Prüfungsverwaltung beauftragt. UnauthorizedExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer:innen, für die Sie mit der Prüfungsverwaltung beauftragt sind. -UnauthorizedSchoolExamOffice: Sie sind nicht mit Prüfungsverwaltung für dieses Institut beauftragt. +UnauthorizedSchoolExamOffice: Sie sind nicht mit Prüfungsverwaltung für diesen Bereich beauftragt. UnauthorizedSystemExamOffice: Sie sind nicht mit systemweiter Prüfungsverwaltung beauftragt. UnauthorizedSystemPrinter: Sie sind nicht mit systemweitem Druck und Briefversand beauftragt. UnauthorizedExternalExamExamOffice: Es existieren keine Prüfungsergebnisse für Nutzer:innen, für die Sie mit der Prüfungsverwaltung beauftragt sind. -UnauthorizedEvaluation: Sie sind nicht mit der Kursumfragenverwaltung beauftragt. -UnauthorizedSchoolLecturer: Sie sind nicht als Veranstalter:in für dieses Institut eingetragen. +UnauthorizedEvaluation: Sie sind nicht mit der Kursartumfragenverwaltung beauftragt. +UnauthorizedSchoolLecturer: Sie sind nicht als Veranstalter:in für diesen Bereich eingetragen. UnauthorizedLecturer: Sie sind nicht als Veranstalter:in für diese Veranstaltung eingetragen. UnauthorizedCorrector: Sie sind nicht als Korrektor:in für diese Veranstaltung eingetragen. UnauthorizedSheetCorrector: Sie sind nicht als Korrektor:in für dieses Übungsblatt eingetragen. @@ -44,11 +44,11 @@ UnauthorizedExamOccurrenceRegistration: Anmeldung zur Prüfung erfolgt nicht ink UnauthorizedExternalExamResult: Sie haben keine Ergebnisse in dieser Prüfung. UnauthorizedParticipant: Angegebener Benutzer/Angegebene Benutzerin ist nicht als Teilnehmer:in dieser Veranstaltung registriert. UnauthorizedParticipantSelf: Sie sind nicht Teilnehmer:in dieser Veranstaltung. -UnauthorizedCourseTime: Dieser Kurs ist momentan nicht freigegeben. -UnauthorizedCourseRegistrationTime: Dieser Kurs erlaubt momentan keine Anmeldungen. +UnauthorizedCourseTime: Diese Kursart ist momentan nicht freigegeben. +UnauthorizedCourseRegistrationTime: Diese Kursart erlaubt momentan keine Anmeldungen. UnauthorizedSheetTime: Dieses Übungsblatt ist momentan nicht freigegeben. UnauthorizedMaterialTime: Dieses Material ist momentan nicht freigegeben. -UnauthorizedTutorialTime: Dieses Tutorium erlaubt momentan keine Anmeldungen. +UnauthorizedTutorialTime: Dieser Kurs erlaubt momentan keine Anmeldungen. UnauthorizedCourseNewsTime: Diese Nachricht ist momentan nicht freigegeben. UnauthorizedExamTime: Diese Prüfung ist momentan nicht freigegeben. UnauthorizedSubmissionOwner: Sie sind an dieser Abgabe nicht beteiligt. @@ -65,11 +65,11 @@ UnauthorizedSystemMessageTime: Diese Systemnachricht ist noch nicht oder nicht m UnauthorizedSystemMessageAuth: Diese Systemnachricht ist nur für angemeldete Benutzer:innen einsehbar. UnknownAuthPredicate tag@String: Authorisierungsprädikat "#{tag}" ist dem System nicht bekannt UnauthorizedSelf: Aktueller Nutzer/Aktuelle Nutzerin ist nicht angegebener Benutzer/angegebene Benutzerin. -UnauthorizedTutorialTutor: Sie sind nicht Tutor:in für dieses Tutorium. -UnauthorizedTutorialTutorControl: Tutor:innen dürfen dieses Tutorium nicht editieren. -UnauthorizedCourseTutor: Sie sind nicht Tutor:in für diesen Kurs. -UnauthorizedTutor: Sie sind nicht Tutor:in. -UnauthorizedTutorialRegisterGroup: Sie sind bereits in einem Tutorium mit derselben Registrierungs-Gruppe. +UnauthorizedTutorialTutor: Sie sind nicht Ausbilder:in für diesen Kurs. +UnauthorizedTutorialTutorControl: Ausbilder:innen dürfen diesen Kurs nicht editieren. +UnauthorizedCourseTutor: Sie sind nicht Ausbilder:in für diese Kursart. +UnauthorizedTutor: Sie sind nicht Ausbilder:in. +UnauthorizedTutorialRegisterGroup: Sie sind bereits in einem Kurs mit derselben Registrierungs-Gruppe eingetragen. UnauthorizedLDAP: Angegebener Nutzer/Angegebene Nutzerin meldet sich nicht mit Fraport Login an. UnauthorizedPWHash: Angegebener Nutzer/Angegebene Nutzerin meldet sich nicht mit FRADrive-Kennung an. UnauthorizedExternalExamListNotEmpty: Liste von externen Prüfungen ist nicht leer @@ -91,10 +91,10 @@ WorkflowRoleUserMismatch: Sie sind nicht einer der vom Workflow geforderten Benu WorkflowRoleAlreadyInitiated: Dieser Workflow wurde bereits initiiert WorkflowRoleNoSuchWorkflowWorkflow: Der angegebene Workflow konnte nicht gefunden werden WorkflowRoleNoPayload: Dieser Workflow enthält keine Daten -CourseNoCapacity: In diesem Kurs sind keine Plätze mehr frei. -TutorialNoCapacity: In dieser Übung sind keine Plätze mehr frei. +CourseNoCapacity: In dieser Kursart sind keine Plätze mehr frei. +TutorialNoCapacity: In diesem Kurs sind keine Plätze mehr frei. ExamOccurrenceNoCapacity: Zu diesem Termin/Raum sind keine Plätze mehr frei. -CourseNotEmpty: In diesem Kurs sind momentan Teilnehmer:innen angemeldet. +CourseNotEmpty: In dieser Kursart sind momentan Teilnehmer:innen angemeldet. LDAPLoginTitle: Fraport Login für interne und externe Nutzer PWHashLoginTitle: Spezieller Funktionsnutzer Login @@ -108,7 +108,7 @@ CampusUserInvalidGivenName: Konnte anhand des Fraport Büko-Logins keinen Vornam CampusUserInvalidSurname: Konnte anhand des Fraport Büko-Logins keinen Nachname ermitteln CampusUserInvalidTitle: Konnte anhand des Fraport Büko-Logins keinen akademischen Titel ermitteln CampusUserInvalidFeaturesOfStudy parseErr@Text: Konnte anhand des Fraport Büko-Logins keine Studiengänge ermitteln -CampusUserInvalidAssociatedSchools parseErr@Text: Konnte anhand des Fraport Büko-Logins keine Institute ermitteln +CampusUserInvalidAssociatedSchools parseErr@Text: Konnte anhand des Fraport Büko-Logins keine Bereiche ermitteln InvalidCredentialsADNoSuchObject: Benutzereintrag existiert nicht InvalidCredentialsADLogonFailure: Ungültiges Passwort InvalidCredentialsADAccountRestriction: Beschränkungen des Fraport Accounts verhindern Login diff --git a/messages/uniworx/categories/authorization/en-eu.msg b/messages/uniworx/categories/authorization/en-eu.msg index 59dad7860..87f044580 100644 --- a/messages/uniworx/categories/authorization/en-eu.msg +++ b/messages/uniworx/categories/authorization/en-eu.msg @@ -24,31 +24,31 @@ UnauthorizedSiteAdmin: You are no system-wide administrator. UnauthorizedSchoolAdmin: You are no administrator for this department. UnauthorizedAdminEscalation: You aren't an administrator for all departments for which this user is an administrator. UnauthorizedExamOffice: You are not part of an exam office. -UnauthorizedEvaluation: You are not charged with course evaluation. +UnauthorizedEvaluation: You are not charged with course type evaluation. UnauthorizedExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam. UnauthorizedSchoolExamOffice: You are not part of an exam office for this school. UnauthorizedSystemExamOffice: You are not charged with system wide exam administration. UnauthorizedSystemPrinter: You are not charged with system wide letter printing. UnauthorizedExternalExamExamOffice: You are not part of the appropriate exam office for any of the participants of this exam. -UnauthorizedSchoolLecturer: You are no lecturer for this department. -UnauthorizedLecturer: You are no administrator for this course. -UnauthorizedCorrector: You are no sheet corrector for this course. +UnauthorizedSchoolLecturer: You are no course administrator for this department. +UnauthorizedLecturer: You are no administrator for this course type. +UnauthorizedCorrector: You are no sheet corrector for this course type. UnauthorizedSheetCorrector: You are no corrector for this sheet. UnauthorizedExamCorrector: You are no corrector for this exam. -UnauthorizedCorrectorAny: You are no corrector for any course. -UnauthorizedRegistered: You are no participant in this course. +UnauthorizedCorrectorAny: You are no corrector for any course type. +UnauthorizedRegistered: You are no participant in this course type. UnauthorizedRegisteredExam: You are not registered for this exam. UnauthorizedRegisteredAnyExam: You are not registered for an exam. UnauthorizedExamResult: You have no results in this exam. UnauthorizedExamOccurrenceRegistration: Registration for exam is not done including occurrence/room. UnauthorizedExternalExamResult: You have no results in this exam. -UnauthorizedParticipant: The specified user is no participant of this course. -UnauthorizedParticipantSelf: You are no participant of this course. -UnauthorizedCourseTime: This course is not currently available. -UnauthorizedCourseRegistrationTime: This course does not currently allow enrollment. +UnauthorizedParticipant: The specified user is no participant of this course type. +UnauthorizedParticipantSelf: You are no participant of this course type. +UnauthorizedCourseTime: This course type is not currently available. +UnauthorizedCourseRegistrationTime: This course type does not currently allow enrollment. UnauthorizedSheetTime: This sheet is not currently available. -UnauthorizedMaterialTime: This course material is not currently available. -UnauthorizedTutorialTime: This tutorial does not currently allow registration. +UnauthorizedMaterialTime: This course type material is not currently available. +UnauthorizedTutorialTime: This course does not currently allow registration. UnauthorizedCourseNewsTime: This news item is not currently available. UnauthorizedExamTime: This exam is not currently available. UnauthorizedSubmissionOwner: You are no submittor for this submission. @@ -59,17 +59,17 @@ UnauthorizedUserSubmission: Users may not directly submit for this exercise shee UnauthorizedCorrectorSubmission: Correctors may not create submissions for this exercise sheet. UnauthorizedCorrectionAnonymous: Correction is not anonymised. DeprecatedRoute: This view is deprecated and will be removed. -UnfreeMaterials: Course material are not publicly accessable. +UnfreeMaterials: Course type material are not publicly accessable. UnauthorizedWrite: You do not have the write permission necessary to perform this action UnauthorizedSystemMessageTime: This system-message is not currently available. UnauthorizedSystemMessageAuth: This system-message is only available to logged in users. UnknownAuthPredicate tag: Auth predicate “#{tag}” is unknown UnauthorizedSelf: You are not the specified user. -UnauthorizedTutorialTutor: You are no tutor for this tutorial. -UnauthorizedTutorialTutorControl: Tutors may not edit this tutorial. -UnauthorizedCourseTutor: You are no tutor for this course. -UnauthorizedTutor: You are no tutor. -UnauthorizedTutorialRegisterGroup: You are already registered for a tutorial with the same registration group. +UnauthorizedTutorialTutor: You are no instructor for this course. +UnauthorizedTutorialTutorControl: Instructors may not edit this course. +UnauthorizedCourseTutor: You are no instructor for this course. +UnauthorizedTutor: You are no instructor. +UnauthorizedTutorialRegisterGroup: You are already registered for a course with the same registration group. UnauthorizedLDAP: Specified user does not log in with their Fraport password. UnauthorizedPWHash: Specified user does not log in with an FRADrive-account. UnauthorizedExternalExamListNotEmpty: List of external exams is not empty @@ -92,8 +92,8 @@ WorkflowRoleAlreadyInitiated: This workflow was already initiated WorkflowRoleNoSuchWorkflowWorkflow: The given workflow could not be found WorkflowRoleNoPayload: This workflow does not contain any data -CourseNoCapacity: Course has reached maximum capacity -TutorialNoCapacity: Tutorial has reached maximum capacity +CourseNoCapacity: Course type has reached maximum capacity +TutorialNoCapacity: Course has reached maximum capacity ExamOccurrenceNoCapacity: Occurrence/Room has reached maximum capacity CourseNotEmpty: There are currently no participants enrolled for this course. diff --git a/messages/uniworx/categories/courses/courses/de-de-formal.msg b/messages/uniworx/categories/courses/courses/de-de-formal.msg index fa44ab8cc..f0df8c433 100644 --- a/messages/uniworx/categories/courses/courses/de-de-formal.msg +++ b/messages/uniworx/categories/courses/courses/de-de-formal.msg @@ -2,10 +2,10 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -FilterCourse: Kurs +FilterCourse: Kursart FilterCourseShort: Kürzel -FilterTerm !ident-ok: Semester -FilterCourseSchoolShort: Institut +FilterTerm !ident-ok: Jahr +FilterCourseSchoolShort: Bereich FilterRegistered: Angemeldet FilterCourseSearch: Volltext-Suche FilterCourseSearchShorthand: Kürzel-Suche @@ -15,7 +15,7 @@ FilterCourseRegisterOpen: Anmeldung möglich CourseRegistered: Angemeldet CourseRegistration: Anmeldung CourseDescription: Beschreibung -CommCourseHeading: Kursmitteilung +CommCourseHeading: Kursartmitteilung CourseLecturers: Kursverwalter:innen CourseLecturerEmail: E-Mail CourseLecturerAlreadyAdded: Diese:r Nutzer:in ist bereits als Kursverwalter:in eingetragen @@ -23,29 +23,29 @@ CourseLecturerType: Rolle LecturerType: Rolle CourseLecturerRightsIdentical: Alle Sorten von Kursverwalter:innen haben identische Rechte. CourseAcceptSubstitutesUntil: Nachrücker:innen akzeptieren bis -CourseAcceptSubstitutesUntilTip: Bis zu welchem Zeitpunkt sollen durch die Zentralanmeldung Nachrücker:innen diesem Kurs zugewiesen werden? Wird kein Datum angegeben werden nach der Initialen Verteilung nie Nachrücker:innen zugewiesen. Diese Frist sollte nicht willkürlich früh bzw. nicht gesetzt werden, um für die Studierenden keine unnötige Beschränkung darzustellen. Geeignet ist z.B. bei einem Seminar wenige Stunden vor dem ersten Treffen zum Verteilen der Themen. +CourseAcceptSubstitutesUntilTip: Bis zu welchem Zeitpunkt sollen durch die Zentralanmeldung Nachrücker:innen dieser Kursart zugewiesen werden? Wird kein Datum angegeben werden nach der Initialen Verteilung nie Nachrücker:innen zugewiesen. Diese Frist sollte nicht willkürlich früh bzw. nicht gesetzt werden, um für die Studierenden keine unnötige Beschränkung darzustellen. Geeignet ist z.B. bei einem Seminar wenige Stunden vor dem ersten Treffen zum Verteilen der Themen. CourseDeregisterNoShow: „Nicht erschienen“ bei Abmeldung -CourseDeregisterNoShowTip: Soll, wenn sich Teilnehmer:innen selbstständig abmelden, für alle Prüfungen dieses Kurses „nicht erschienen“ als Prüfungsleistung eingetragen werden? Dies geschieht einmalig bei der Abmeldung (sofern nicht bereits eine Prüfungsleistung existiert) und automatisch beim Anlegen von neuen Prüfungen. -CourseSchool: Institut -CourseSchoolMultipleTip: Es stehen für Sie mehrere Institute zur Auswahl. Stellen Sie bitte sicher, dass Sie das für den Kurs korrekte Institut wählen. -CourseName: Kurstitel +CourseDeregisterNoShowTip: Soll, wenn sich Teilnehmer:innen selbstständig abmelden, für alle Prüfungen dieser Kursart „nicht erschienen“ als Prüfungsleistung eingetragen werden? Dies geschieht einmalig bei der Abmeldung (sofern nicht bereits eine Prüfungsleistung existiert) und automatisch beim Anlegen von neuen Prüfungen. +CourseSchool: Bereich +CourseSchoolMultipleTip: Es stehen für Sie mehrere Bereiche zur Auswahl. Stellen Sie bitte sicher, dass Sie das für die Kursart korrekte Bereich wählen. +CourseName: Kursarttitel CourseShorthand: Kürzel -CourseShorthandUnique: Muss nur innerhalb Institut und Semester eindeutig sein. Wird verbatim in die Url der Kursseite übernommen. -CourseSemester !ident-ok: Semester +CourseShorthandUnique: Muss nur innerhalb Bereich und Jahr eindeutig sein. Wird verbatim in die Url der Kursartseite übernommen. +CourseSemester !ident-ok: Jahr CourseDescriptionPlaceholder: Bitte mindestens die Modulbeschreibung angeben CourseHomepageExternal: Externe Homepage -CourseSemesterMultipleTip: Es stehen für Sie aktuell mehrere Semester zur Auswahl. Stellen Sie bitte sicher, dass Sie das für den Kurs korrekte Semester wählen. +CourseSemesterMultipleTip: Es stehen für Sie aktuell mehrere Jahre zur Auswahl. Stellen Sie bitte sicher, dass Sie das für die Kursart korrekte Jahr wählen. CourseHomepageExternalPlaceholder: Optionale externe URL CourseVisibleFrom: Sichtbar ab CourseVisibleTo: Sichtbar bis -CourseVisibleFromTip: Ab diesem Zeitpunkt ist der Kurs für andere Nutzer:innen sichtbar. Ohne Datum ist der Kurs nie für andere Nutzer:innen sichtbar. Dozierende, Assistent:innen, Tutor:innen, Korrektor:innen, angemeldete Teilnehmer:innen sowie Bewerber:innen dieses Kurses sind nicht betroffen. Nimmt der Kurs an einer Zentralanmeldung teil wird die Kurssichtbarkeit während der Bewerbungsphase forciert. -CourseVisibleToTip: Der Kurs ist ab "Sichtbar ab" bis zu diesem Zeitpunkt für andere Nutzer sichtbar. Ohne Datum bleibt ein sichtbarer Kurs unbegrenzt sichtbar. -CourseMaterialFree: Das Kursmaterial ist ohne Anmeldung frei zugänglich -CourseFormSectionRegistration: Anmeldung zum Kurs +CourseVisibleFromTip: Ab diesem Zeitpunkt ist die Kursart für andere Nutzer:innen sichtbar. Ohne Datum ist die Kursart nie für andere Nutzer:innen sichtbar. Kursverwaltende, Assistent:innen, Ausbilder:innen, Korrektor:innen, angemeldete Teilnehmer:innen sowie Bewerber:innen dieser Kursart sind nicht betroffen. Nimmt die Kursart an einer Zentralanmeldung teil wird die Kursartsichtbarkeit während der Bewerbungsphase forciert. +CourseVisibleToTip: Die Kursart ist ab "Sichtbar ab" bis zu diesem Zeitpunkt für andere Nutzer sichtbar. Ohne Datum bleibt ein sichtbare Kursart unbegrenzt sichtbar. +CourseMaterialFree: Das Kursartmaterial ist ohne Anmeldung frei zugänglich +CourseFormSectionRegistration: Anmeldung zur Kursart CourseFormSectionAdministration: Verwaltung CourseCapacity: Kapazität -CourseCapacityTip: Anzahl erlaubter Kursanmeldungen, leer lassen für unbeschränkte Kurskapazität -CourseSecretTip: Anmeldung zum Kurs erfordert Eingabe des Passworts, sofern gesetzt +CourseCapacityTip: Anzahl erlaubter Kursanmeldungen, leer lassen für unbeschränkte Kursartkapazität +CourseSecretTip: Anmeldung zur Kursart erfordert Eingabe des Passworts, sofern gesetzt CourseSecretFormat: beliebige Zeichenkette CourseSecretWrong: Falsches Passwort CourseSecret: Zugangspasswort @@ -59,42 +59,43 @@ CourseVisibilityEndMustBeAfterStart: Ende des Sichtbarkeitszeitraums muss nach d CourseRegistrationEndMustBeAfterStart: Ende des Anmeldezeitraums muss nach dem Anfang liegen CourseDeregistrationEndMustBeAfterStart: Ende des Abmeldezeitraums muss nach dem Anfang des Anmeldezeitraums liegen CourseUserMustBeLecturer: Aktuelle:r Benutzer:in muss als Kursverwalter:in eingetragen sein -CourseShorthandTooLong: Lange Kurskürzel können zu Problemen bei der Darstellung und der Kommunikation mit den Studierenden führen. Bitte wählen Sie ein weniger langes Kürzel, falls möglich. -CourseNotAlwaysVisibleDuringRegistration: Um Studierenden über den gesamten Anmeldezeitraum hinweg die Anmeldung zum Kurs zu ermöglichen, sollte der Kurs auch über den gesamten Anmeldezeitraum hinweg sichtbar sein (dies ist aktuell nicht gegeben). -NoSuchTerm tid@TermId: Semester #{tid} gibt es nicht. -NoSuchSchool ssh@SchoolId: Institut #{ssh} gibt es nicht. -NoSuchCourseShorthand csh@CourseShorthand: Kein Kurs mit Kürzel #{csh} bekannt. -NoSuchCourse: Keinen passenden Kurs gefunden. -CourseNewDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} konnte nicht erstellt werden: Es gibt bereits einen anderen Kurs mit dem selben Kürzel oder Titel in diesem Semester und Institut. +CourseShorthandTooLong: Lange Kursartkürzel können zu Problemen bei der Darstellung und der Kommunikation mit den Studierenden führen. Bitte wählen Sie ein weniger langes Kürzel, falls möglich. +CourseNotAlwaysVisibleDuringRegistration: Um Studierenden über den gesamten Anmeldezeitraum hinweg die Anmeldung zur Kursart zu ermöglichen, sollte die Kursart auch über den gesamten Anmeldezeitraum hinweg sichtbar sein (dies ist aktuell nicht gegeben). +NoSuchTerm tid@TermId: Jahr #{tid} gibt es nicht. +NoSuchSchool ssh@SchoolId: Bereich #{ssh} gibt es nicht. +NoSuchCourseShorthand csh@CourseShorthand: Keine Kursart mit Kürzel #{csh} bekannt. +NoSuchCourse: Keine passende Kursart gefunden. +CourseNewDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} konnte nicht erstellt werden: Es gibt bereits einen andere Kursart mit dem selben Kürzel oder Titel in diesem Jahr und Bereich. CourseInvalidInput: Eingaben bitte korrigieren. -CourseEditTitle: Kurs editieren/anlegen -CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert. -CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen anderen Kurs mit dem selben Kürzel oder Titel in diesem Semester und Institut. -CourseLecturer: Dozent:in -MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursteilnahme -CourseParticipantInviteHeading courseName@Text: Einladung zum Kursteilnahmer für #{courseName} -CourseParticipantInviteExplanation: Sie wurden eingeladen, an einem Kurs teilzunehmen. +CourseEditTitle: Kursart editieren/anlegen +CourseEditOk tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} wurde erfolgreich geändert. +CourseEditDupShort tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} konnte nicht geändert werden: Es gibt bereits einen andere Kursart mit dem selben Kürzel oder Titel in diesem Jahr und Bereich. +CourseLecturer: Kursverwalter:in +MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zur Kursartteilnahme +CourseParticipantInviteHeading courseName@Text: Einladung zum Kursartteilnahmer für #{courseName} +CourseParticipantInviteExplanation: Sie wurden eingeladen, an einer Kursart teilzunehmen. CourseParticipantInviteField: Einzuladende E-Mail-Adressen CourseParticipantInvitationAccepted courseName@Text: Sie wurden als Teilnehmer:in für #{courseName} eingetragen CourseParticipantEnlistDirectly: Bekannte Nutzer:innen sofort als Teilnehmer:in eintragen CourseSubmissionGroup: Feste Abgabegruppe SubmissionGroupEmptyIsUnsetTip: Leer lassen um Benutzer:innen aus den jeweiligen Abgabegruppen ersatzlos zu entfernen -CourseParticipantsRegisterHeading: Kursteilnehmer:innen hinzufügen -CourseParticipantsRegisterActionAddParticipants: Personen zum Kurs anmelden -CourseParticipantsRegisterActionAddTutorialMembers: Personen zu Kurs und Übungsgruppe anmelden -CourseParticipantsRegisterUsersField: Zum Kurs anzumeldende Personen +CourseParticipantsRegisterHeading: Kursartteilnehmer:innen hinzufügen +CourseParticipantsRegisterActionAddParticipants: Personen zur Kursart anmelden +CourseParticipantsRegisterActionAddTutorialMembers: Personen zur Kursart und Kursgruppe anmelden +CourseParticipantsRegisterUsersField: Zur Kursart anzumeldende Personen CourseParticipantsRegisterUsersFieldTip: Bitte Ausweiskartennummer inklusive Punkt, Fraport Personalnummer oder Email angeben. Mehrere Personen bitte mit Komma oder Leerzeichen trennen. -CourseParticipantsRegisterTutorialOption: Kursteilnehmer:innen zu Übungsgruppe anmelden? -CourseParticipantsRegisterTutorialField: Übungsgruppe -CourseParticipantsRegisterTutorialFieldTip: Ist aktuell keine Übungsgruppe mit diesem Namen vorhanden, wird eine neue erstellt. Ist bereits eine Übungsgruppe mit diesem Namen vorhanden, werden die Kursteilnehmenden dieser hinzugefügt. +CourseParticipantsRegisterTutorialOption: Kursartteilnehmer:innen zu Kursgruppe anmelden? +CourseParticipantsRegisterTutorialField: Kursgruppe +CourseParticipantsRegisterTutorialFieldTip: Ist aktuell keine Kursgruppe mit diesem Namen vorhanden, wird eine neue erstellt. Ist bereits eine Kursgruppe mit diesem Namen vorhanden, werden die Kursartteilnehmenden dieser hinzugefügt. CourseParticipantsRegisterNoneGiven: Es wurden keine anzumeldenden Personen angegeben! CourseParticipantsRegisterNotFoundInAvs n@Int: Zu #{n} #{pluralDE n "Angabe konnte keine übereinstimmende Person" "Angaben konnten keine übereinstimmenden Personen"} im AVS gefunden werden +CourseParticipantsRegisterTutorialFirstDayTip: Wenn ein neuer Kurs gemäß einer Vorlage erstellt wird, werden die Zeiten gemäß dem Starttag angepasst CourseParticipantsInvited n@Int: #{n} #{pluralDE n "Einladung" "Einladungen"} per E-Mail verschickt -CourseParticipantsAlreadyRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits zum Kurs angemeldet -CourseParticipantsAlreadyTutorialMember n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits in dieser Übungsgruppe angemeldet -CourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zum Kurs angemeldet -CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Übungsgruppe angemeldet +CourseParticipantsAlreadyRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits zur Kursart angemeldet +CourseParticipantsAlreadyTutorialMember n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} #{pluralDE n "ist" "sind"} bereits in dieser Kursgruppe angemeldet +CourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Kursart angemeldet +CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Kursgruppe angemeldet CourseParticipantsRegisterConfirmationHeading: Teilnehmer:innen hinzufügen CourseParticipantsRegisterUnnecessary: Alle angeforderten Anmeldungen sind bereits vorhanden. Es wurden keine Änderungen vorgenommen. CourseParticipantsRegisterConfirmInvalid: Ungültiges Bestätigungsformular! @@ -105,20 +106,20 @@ CourseRegistrationFiles: Datei(en) zur Anmeldung CourseRegistrationFilesNeedReupload: Dateien zur Anmeldung müssen neu hochgeladen werden, wann immer die Anmeldung angepasst wird CourseRegistrationFile: Datei zur Anmeldung CourseRegistrationArchive: Zip-Archiv der Datei(en) zur Anmeldung -CourseDeregistrationNoShow: Wenn Sie sich vom Kurs abmelden, wird für alle Prüfungen des Kurses „nicht erschienen“ gemeldet. Wenn Sie gute Gründe vorzuweisen haben, warum Ihre Abmeldung nicht selbstverschuldet ist, kontaktieren Sie bitte eine:n Kursverwalter:in. Diese haben die Möglichkeit Sie ohne permanente Eintragung im System abzumelden. -CourseDeregistrationFromInvisibleCourse: Dieser Kurs ist nur für angemeldete Teilnehmer:innen und Bewerber:innen sichtbar. Wenn Sie sich jetzt abmelden, können Sie danach nicht wieder auf den Kurs zugreifen! -CourseDeregistrationNoReRegistration: Wenn Sie sich jetzt vom Kurs abmelden, können Sie sich nicht wieder selbstständig anmelden. +CourseDeregistrationNoShow: Wenn Sie sich von der Kursart abmelden, wird für alle Prüfungen dieser Kursart „nicht erschienen“ gemeldet. Wenn Sie gute Gründe vorzuweisen haben, warum Ihre Abmeldung nicht selbstverschuldet ist, kontaktieren Sie bitte eine:n Kursverwalter:in. Diese haben die Möglichkeit Sie ohne permanente Eintragung im System abzumelden. +CourseDeregistrationFromInvisibleCourse: Diese Kursart ist nur für angemeldete Teilnehmer:innen und Bewerber:innen sichtbar. Wenn Sie sich jetzt abmelden, können Sie danach nicht wieder auf die Kursart zugreifen! +CourseDeregistrationNoReRegistration: Wenn Sie sich jetzt von der Kursart abmelden, können Sie sich nicht wieder selbstständig anmelden. LoginNecessary: Bitte melden Sie sich dazu vorher an! RegisterRetry: Sie wurden noch nicht angemeldet. Drücken Sie dazu den Knopf "Anmelden" -CourseRegisterOk: Erfolgreich zum Kurs angemeldet -CourseDeregisterOk: Erfolgreich vom Kurs abgemeldet -CourseApplyOk: Erfolgreich zum Kurs beworben -CourseRetractApplyOk: Bewerbung zum Kurs erfolgreich zurückgezogen +CourseRegisterOk: Erfolgreich zur Kursart angemeldet +CourseDeregisterOk: Erfolgreich von der Kursart abgemeldet +CourseApplyOk: Erfolgreich zur Kursart beworben +CourseRetractApplyOk: Bewerbung zur Kursart erfolgreich zurückgezogen CourseMemberOf: Teilnehmer:in von CourseAssociatedWith: assoziiert mit CourseLastEdit: Letzte Änderung CourseUserNote: Notiz -CourseUserNoteTooltip: Nur für Verwalter dieses Kurses einsehbar +CourseUserNoteTooltip: Nur für Verwalter dieser Kursart einsehbar CourseUserNoteSaved: Notizänderungen gespeichert CourseUserNoteDeleted: Teilnehmernotiz gelöscht CourseCourseMembers: Teilnehmer:innen @@ -126,9 +127,9 @@ CourseUserExamsResultSet count@Int64: Ergebnis zu #{show count} #{pluralDE count CourseUserExamResultDoesNotMatchMode examn@ExamName: Gewähtes Ergebnis passt nicht zu Bewertungsmodus von Prüfung „#{examn}“. CourseUserExamsDeregistered count@Int64: Teilnehmer:in von #{show count} #{pluralDE count "Prüfung" "Prüfungen"} abgemeldet CourseUserNoExamsDeregistered: Teilnehmer:in ist zu keiner der gewählten Prüfungen angemeldet -CourseUserTutorialsDeregistered count@Int64: Teilnehmer:in von #{show count} #{pluralDE count "Tutorium" "Tutorien"} abgemeldet -CourseUserNoTutorialsDeregistered: Teilnehmer:in ist zu keinem der gewählten Tutorien angemeldet -CourseUserTutorials: Angemeldete Tutorien +CourseUserTutorialsDeregistered count@Int64: Teilnehmer:in von #{show count} #{pluralDE count "Kurs" "Kurse"} abgemeldet +CourseUserNoTutorialsDeregistered: Teilnehmer:in ist zu keinem der gewählten Kurse angemeldet +CourseUserTutorials: Angemeldete Kurse CourseUserExams: Angemeldete Prüfungen CourseUserSheets: Übungsblätter CsvColumnUserName: Voller Name des/der Teilnehmers/Teilnehmerin @@ -137,76 +138,76 @@ CsvColumnUserSex: Geschlecht CsvColumnUserBirthday: Geburtstag CsvColumnUserEmail: E-Mail-Adresse des/der Teilnehmers/Teilnehmerin CsvColumnUserCourseStudyFeatures: Alle relevanten Studiendaten des/der Teilnehmers/Teilnehmerin als Semikolon (;) separierte Liste -CsvColumnUserRegistration: Zeitpunkt der Anmeldung zum Kurs (ISO 8601) -CsvColumnUserTutorial: Tutorien zu denen der/die Teilnehmer/Teilnehmerin angemeldet ist, als Semikolon (;) separierte Liste. Für Registrierungs-Gruppen unter den Tutorien gibt es jeweils eine weitere Spalte. Die Registrierungs-Gruppen-Spalten enthalten jeweils maximal ein Tutorium pro Teilnehmer:in. Sind alle Tutorien in Registrierungs-Gruppen, so gibt es keine Spalte "tutorial". +CsvColumnUserRegistration: Zeitpunkt der Anmeldung zur Kursart (ISO 8601) +CsvColumnUserTutorial: Kurse zu denen der/die Teilnehmer/Teilnehmerin angemeldet ist, als Semikolon (;) separierte Liste. Für Registrierungs-Gruppen unter den Kurse gibt es jeweils eine weitere Spalte. Die Registrierungs-Gruppen-Spalten enthalten jeweils maximal ein Kurs pro Teilnehmer:in. Sind alle Kurse in Registrierungs-Gruppen, so gibt es keine Spalte "Kurs". CsvColumnUserExam: Prüfungen zu denen der/die Teilnehmer/Teilnehmerin angemeldet ist, als Semikolon (;) separierte Liste. CsvColumnUserSubmissionGroup: Registrierte Abgabegruppe CsvColumnUserNote: Notizen zum/zur Teilnehmer/Teilnehmerin CsvColumnUserSurname: Nachname(n) des Teilnehmers/der Teilnehmerin CsvColumnUserFirstName: Vorname(n) des Teilnehmers/der Teilnehmerin CourseUserCsvName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-teilnehmer -CourseUserTutorial: Angemeldetes Tutorium +CourseUserTutorial: Angemeldeter Kurs CourseUserExam: Angemeldete Prüfung CourseUserCsvSheetName tid@TermId ssh@SchoolId csh@CourseShorthand: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Teilnehmer CourseUserCsvIncludeSheets: Übungsblätter CourseUserCsvIncludeSheetsTip: Soll die exportierte CSV-Datei zusätzlich eine Spalte pro Übungsblatt enthalten? RegisteredSince: Angemeldet seit CourseUserState: Zustand -CourseTutorial: Tutorium +CourseTutorial: Kurs CourseExam: Prüfung ExerciseSheet: Übungsblatt -CourseUsersDeregistered count@Int64: #{show count} Teilnehmer:innen vom Kurs abgemeldet -CourseUsersTutorialRegistered count@Int64: #{show count} Teilnehmer:innen zum Tutorium angemeldet +CourseUsersDeregistered count@Int64: #{show count} Teilnehmer:innen von der Kursart abgemeldet +CourseUsersTutorialRegistered count@Int64: #{show count} Teilnehmer:innen zum Kurs angemeldet CourseUsersExamRegistered count@Int64: #{show count} Teilnehmer:innen zur Prüfung angemeldet CourseUsersSubmissionGroupSetNew count@Int64: #{show count} Benutzer:innen der festen Abgabegruppe zugeordnet CourseUsersSubmissionGroupUnset count@Int64: #{show count} Benutzer:innen aus ihren jeweiligen festen Abgabegruppen entfernt CourseUsersStateSet count@Int64: Zustand von #{show count} #{pluralDE count "Benutzer:in" "Benutzer:innen"} angepasst #templates/course.hamlet -LecturerFor: Dozent:in -LecturersFor: Dozierende +LecturerFor: Kursverwalter:in +LecturersFor: Kursvewaltende AssistantFor: Assistent:in AssistantsFor: Assistent:innen CourseAdminFor: Kursadministration -TutorsFor n@Int: #{pluralDE n "Tutor:in" "Tutor:innen"} +TutorsFor n@Int: #{pluralDE n "Ausbilder:in" "Ausbilder:innen"} CorrectorsFor n@Int: #{pluralDE n "Korrektor:in" "Korrektor:innen"} -CourseParticipantsHeading: Kursteilnehmer:innen +CourseParticipantsHeading: Kursartteilnehmer:innen CourseParticipantsCount n@Int !ident-ok: #{n} CourseParticipantsCountOf n@Int m@Int: #{n} von #{m} CourseVisibility: Sichtbarkeit -CourseInvisible: Dieser Kurs ist momentan nur für Dozierende, Assistent:innen, Tutor:innen, Korrektor:innen, angemeldete Teilnehmer:innen und Bewerber:innen sichtbar. +CourseInvisible: Diese Kursart ist momentan nur für Kursverwaltende, Assistent:innen, Ausbilder:innen, Korrektor:innen, angemeldete Teilnehmer:innen und Bewerber:innen sichtbar. CourseRegistrationInterval: Anmeldung CourseDirectRegistrationInterval: Direkte Anmeldung CourseDeregisterUntil time@Text: Abmeldung nur bis #{time} CourseMaterial !ident-ok: Material -NotRegistered: Nicht zum Kurs angemeldet -CourseMaterialNotFree: Das Kursmaterial ist nur für Mitglieder des Kurses einsehbar, also z.B. für Teilnehmer:innen, Tutor:innen, Korrektor:innen und Verwalter:innen. -CourseMaterialsFoundHere: Material zum Kurs finden Sie hier -CourseMaterialsNoneVisible: Aktuell gibt es zu diesem Kurs kein Material, oder nur Material auf das Sie keinen Zugriff haben (z.B. aufgrund von Fristen bzgl. der Sichtbarkeit). -CourseSheetsFoundHere: Die Übungsblatter zum Kurs finden Sie hier -CourseSheetsNoneVisible: Aktuell gibt es zu diesem Kurs keine Übungsblätter, oder nur Übungsblätter auf die Sie keinen Zugriff haben (z.B. aufgrund von Fristen bzgl. der Sichtbarkeit). +NotRegistered: Nicht zur Kursart angemeldet +CourseMaterialNotFree: Das Kursartmaterial ist nur für Mitglieder der Kursart einsehbar, also z.B. für Teilnehmer:innen, Ausbilder:innen, Korrektor:innen und Verwalter:innen. +CourseMaterialsFoundHere: Material zur Kursart finden Sie hier +CourseMaterialsNoneVisible: Aktuell gibt es zu dieser Kursart kein Material, oder nur Material auf das Sie keinen Zugriff haben (z.B. aufgrund von Fristen bzgl. der Sichtbarkeit). +CourseSheetsFoundHere: Die Übungsblatter zur Kursart finden Sie hier +CourseSheetsNoneVisible: Aktuell gibt es zu dieser Kursart keine Übungsblätter, oder nur Übungsblätter auf die Sie keinen Zugriff haben (z.B. aufgrund von Fristen bzgl. der Sichtbarkeit). SheetListCourse: Übungsblätter CourseExams: Prüfungen -CourseTutorials: Tutorien +CourseTutorials: Kurse #templates course/user CourseUserCorrections: Abgaben CourseSubmissionGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Abgabe" "Abgaben"} CourseSingleUserExams: Prüfungen -CourseSingleUserTutorials: Tutorien +CourseSingleUserTutorials: Kurse Surname: Nachname(n) FirstName: Vorname(n) Title: Titel NoMatrikelKnown: Keine Matrikelnummer -CourseDeregisterLecturerTip: Wenn Sie den/die Teilnehmer/Teilnehmerin vom Kurs abmelden kann es sein, dass sie Zugriff auf diese Daten verlieren +CourseDeregisterLecturerTip: Wenn Sie den/die Teilnehmer/Teilnehmerin von der Kursart abmelden kann es sein, dass sie Zugriff auf diese Daten verlieren StudyTerms: Studiengänge NoStudyTermsKnown: Keine Studiengänge bekannt CourseMembersCountOf n@Int mbNum@(Maybe Int): #{n} Kursanmeldungen #{maybeToMessage " von " mbNum " möglichen"} CourseLoginToApply: Um sich zum Kurz zu bewerben müssen Sie sich zunächst in Uni2work anmelden -CourseLoginToRegister: Um sich zum Kurs anzumelden müssen Sie zunächst in Uni2work anmelden +CourseLoginToRegister: Um sich zur Kursart anzumelden müssen Sie zunächst in Uni2work anmelden CourseLecInviteHeading courseName@Text: Einladung zum/zur Kursverwalter/Kursverwalterin für #{courseName} -CourseLecInviteExplanation: Sie wurden eingeladen, Verwalter:in für einen Kurs zu sein. +CourseLecInviteExplanation: Sie wurden eingeladen, Verwalter:in für eine Kursart zu sein. CourseUserHasPersonalisedSheetFilesFilter: Teilnehmer:in hat personalisierte Übungsblatt-Dateien für HeadingCourseMembers: Teilnehmer:innen @@ -214,7 +215,7 @@ CourseAssistant: Assistent:in CourseParticipantStateIsInactive: Teilnehmer:in ist nicht aktiv CourseParticipantStateIsActive: Teilnehmer:in ist aktiv CourseUserSendMail: Nachricht an Teilnehmer:in senden -CourseUserRegisterTutorial: Tutorium eintragen +CourseUserRegisterTutorial: Kurs eintragen CourseUserRegisterExam: Prüfung eintragen CourseUserDownloadPersonalisedSheetFiles: Personalisierte Übungsblätter herunterladen CourseUserSetSubmissionGroup: Gruppenabgabe hinzufügen @@ -227,8 +228,8 @@ TutorialRegistered: Angemeldet TutorialRegisterFrom: Anmeldungen ab TutorialRegisterTo: Anmeldungen bis -CourseDeleteQuestion: Wollen Sie den unten aufgeführten Kurs wirklich löschen? -CourseDeleted: Kurs gelöscht +CourseDeleteQuestion: Wollen Sie den unten aufgeführte Kursart wirklich löschen? +CourseDeleted: Kursart gelöscht UtilEditedBy name@Text time@Text: #{time} durch #{name} CourseDate: Datum @@ -236,11 +237,12 @@ MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{ti LecturerInvitationAccepted lType@Text csh@CourseShorthand: Sie wurden als #{lType} für #{csh} eingetragen CourseExamRegistrationTime: Angemeldet seit CourseParticipantStateIsActiveFilter: Ansicht -CourseApply: Zum Kurs bewerben +CourseApply: Zur Kursart bewerben CourseAdministrator: Kursadministrator:in CourseAvsRegisterTitle: Teilnehmer:innen anmelden CourseAvsRegisterParticipants: Teilnehmer:innen CourseAvsRegisterParticipantsTip: Mehrere Teilnehmer:innen mit Komma separieren -CourseQualifications n@Int: Assoziierte #{pluralDE n "Qualifikation" "Qualifikationen"} \ No newline at end of file +CourseQualifications n@Int: Assoziierte #{pluralDE n "Qualifikation" "Qualifikationen"} +CourseCertificate course@Text: Teilnahmebescheinung #{course} \ No newline at end of file diff --git a/messages/uniworx/categories/courses/courses/en-eu.msg b/messages/uniworx/categories/courses/courses/en-eu.msg index ae25a7187..9f14a46a7 100644 --- a/messages/uniworx/categories/courses/courses/en-eu.msg +++ b/messages/uniworx/categories/courses/courses/en-eu.msg @@ -4,7 +4,7 @@ FilterCourse: Course FilterCourseShort: Shorthand -FilterTerm: Semester +FilterTerm: Year FilterCourseSchoolShort: Department FilterRegistered: Enrolled FilterCourseSearch: Text search @@ -15,7 +15,7 @@ FilterCourseRegisterOpen: Enrolment is allowed CourseRegistered: Enrolled CourseRegistration: Enrolment CourseDescription: Description -CommCourseHeading: Course message +CommCourseHeading: Course type message CourseLecturers: Course administrators CourseLecturerEmail: Email CourseLecturerAlreadyAdded: This user is already configured as a course administrator @@ -25,27 +25,27 @@ CourseLecturerRightsIdentical: All sorts of course administrators have the same CourseAcceptSubstitutesUntil: Accept substitute registrations until CourseAcceptSubstitutesUntilTip: Until which time should substitute registrations through the central allocation be accepted to fill free places in the course? If left empty no substitute registrations will be made. This deadline should not arbitrarily be set early or ommitted so as to not be an unneccesarily restrictive for students. For a seminar a valid choice might be a few hours before the first meeting in which topics will be assigned. CourseDeregisterNoShow: Record “no show” when deregistering -CourseDeregisterNoShowTip: Should “no show” be recorded as the exam achievement for all exams associated with this course automatically whenever a course participant deregisters themselves? This would be done once upon deregistration (if no other achievement exists for the given exam) and automatically whenever a new exam is created. +CourseDeregisterNoShowTip: Should “no show” be recorded as the exam achievement for all exams associated with this course type automatically whenever a course type participant deregisters themselves? This would be done once upon deregistration (if no other achievement exists for the given exam) and automatically whenever a new exam is created. CourseSchool: Department CourseSchoolMultipleTip: You may select from among multiple departments. Please ensure that you select the appropriate department for your course. CourseName: Title CourseShorthand: Shorthand -CourseShorthandUnique: Needs to be unique within school and semester. Will be used verbatim within the url of the course page. -CourseSemester: Semester +CourseShorthandUnique: Needs to be unique within school and year. Will be used verbatim within the url of the course type page. +CourseSemester: Year CourseDescriptionPlaceholder: Please include the module description CourseHomepageExternalPlaceholder: Optional external URL CourseHomepageExternal: External homepage -CourseSemesterMultipleTip: You are currently allowed to select from among multiple semesters. Please ensure that you select the appropriate semester for your course. +CourseSemesterMultipleTip: You are currently allowed to select from among multiple years. Please ensure that you select the appropriate year for your course. CourseVisibleFrom: Visible from CourseVisibleTo: Visible to -CourseVisibleFromTip: The course will be visible to others from this date onward. When left empty the course will never be visible to other users. This does not affect lecturers, assistants, tutors, correctors, enrolled participants and applicants of/to this course. If the course participates in a central allocation, the course visibility will be forced during the application phase. -CourseVisibleToTip: Other users will be able to see the course from "Visible From" up to this date. When left empty visible courses will remain visible indefinitely. -CourseMaterialFree: Course material is publicly accessible +CourseVisibleFromTip: The course type will be visible to others from this date onward. When left empty the course type will never be visible to other users. This does not affect course administrators, assistants, instructors, correctors, enrolled participants and applicants of/to this course. If the course type participates in a central allocation, the course type visibility will be forced during the application phase. +CourseVisibleToTip: Other users will be able to see the course type from "Visible From" up to this date. When left empty visible courses will remain visible indefinitely. +CourseMaterialFree: Course type material is publicly accessible CourseFormSectionRegistration: Registration CourseFormSectionAdministration: Administration CourseCapacity: Capacity CourseCapacityTip: Maximum permissable number of enrolments for this course; leave empty for unlimited capacity -CourseSecretTip: Enrollment for this course will require the password, if set +CourseSecretTip: Enrollment for this course type will require the password, if set CourseSecretFormat: Arbitrary string CourseSecretWrong: Wrong password CourseSecret: Access password @@ -59,18 +59,18 @@ CourseVisibilityEndMustBeAfterStart: The end of the visibility period must be af CourseRegistrationEndMustBeAfterStart: The end of the registration period must be after its start CourseDeregistrationEndMustBeAfterStart: The end of the deregistration period must be after the start of the registration period CourseUserMustBeLecturer: The current user needs to be a course administrator -CourseShorthandTooLong: Long course shorthands may lead to display issues and might complicate communication with students. Please choose a more concise shorthand if possible. -CourseNotAlwaysVisibleDuringRegistration: To allow for students to register, the course should also be visible during the entire registration period (which is currently not the case). -NoSuchTerm tid: Semester #{tid} does not exist. +CourseShorthandTooLong: Long course type shorthands may lead to display issues and might complicate communication with students. Please choose a more concise shorthand if possible. +CourseNotAlwaysVisibleDuringRegistration: To allow for students to register, the course type should also be visible during the entire registration period (which is currently not the case). +NoSuchTerm tid: Year #{tid} does not exist. NoSuchSchool ssh: Department #{ssh} does not exist. -NoSuchCourseShorthand csh: There is no course with shorthand #{csh}. -NoSuchCourse: No such course found. -CourseNewDupShort tid ssh csh: Could not create course #{tid}-#{ssh}-#{csh}. Another course with the same shorthand or title already exists for the given semester and school. +NoSuchCourseShorthand csh: There is no course type with shorthand #{csh}. +NoSuchCourse: No such course type found. +CourseNewDupShort tid ssh csh: Could not create course type #{tid}-#{ssh}-#{csh}. Another course type with the same shorthand or title already exists for the given year and school. CourseInvalidInput: Invalid input CourseEditTitle: Edit/Create course -CourseEditOk tid ssh csh: Successfully edited course #{tid}-#{ssh}-#{csh} -CourseEditDupShort tid ssh csh: Could not edit course #{tid}-#{ssh}-#{csh}. Another course with the same shorthand or title already exists for the given semester and school. -CourseLecturer: Lecturer +CourseEditOk tid ssh csh: Successfully edited course type #{tid}-#{ssh}-#{csh} +CourseEditDupShort tid ssh csh: Could not edit course type #{tid}-#{ssh}-#{csh}. Another course type with the same shorthand or title already exists for the given year and school. +CourseLecturer: Course administrator MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Invitaion to join the course CourseParticipantInviteHeading courseName: Invitation to enrol for #{courseName} CourseParticipantInviteExplanation: You were invited to be a participant of a course. @@ -79,23 +79,24 @@ CourseParticipantInvitationAccepted courseName: You were enrolled in #{courseNam CourseParticipantEnlistDirectly: Enrol known users directly CourseSubmissionGroup: Registered submission group SubmissionGroupEmptyIsUnsetTip: Leave empty to remove users from their respective submission groups -CourseParticipantsRegisterHeading: Add course participants -CourseParticipantsRegisterActionAddParticipants: Add course participants -CourseParticipantsRegisterActionAddTutorialMembers: Add course and tutorial participants +CourseParticipantsRegisterHeading: Add course type participants +CourseParticipantsRegisterActionAddParticipants: Add course type participants +CourseParticipantsRegisterActionAddTutorialMembers: Add course participants CourseParticipantsRegisterUsersField: Persons to register for course CourseParticipantsRegisterUsersFieldTip: Please enter id card no (including dot), Fraport personnel number or email. Please separate multiple entries with comma or space. -CourseParticipantsRegisterTutorialOption: Register course participants for tutorial? -CourseParticipantsRegisterTutorialField: Tutorial -CourseParticipantsRegisterTutorialFieldTip: If there is no tutorial with this name, a new one will be created. If there is a tutorial with this name, the course participants will be registered for it. +CourseParticipantsRegisterTutorialOption: Register course type participants for course? +CourseParticipantsRegisterTutorialField: Course +CourseParticipantsRegisterTutorialFieldTip: If there is no course with this name, a new one will be created. If there is a course with this name, the course type participants will be registered for it. CourseParticipantsRegisterNoneGiven: No persons given to register! CourseParticipantsRegisterNotFoundInAvs n: For #{n} #{pluralEN n "entry no corresponding person" "entries no corresponding persons"} could be found in AVS +CourseParticipantsRegisterTutorialFirstDayTip: If a new course is created and a template exists, its dates are adjusted according to the start date CourseParticipantsRegisterUnnecessary: All requested registrations have already been saved. No actions have been performed. CourseParticipantsInvited n: #{n} #{pluralEN n "invitation" "invitations"} sent via email -CourseParticipantsAlreadyRegistered n: #{n} #{pluralEN n "participant is" "participants are"} already course #{pluralEN n "member" "members"} -CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "participants are"} already registered for this tutorial +CourseParticipantsAlreadyRegistered n: #{n} #{pluralEN n "participant is" "participants are"} already course type #{pluralEN n "member" "members"} +CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "participants are"} already registered for this course CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course -CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for tutorial +CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course CourseParticipantsRegisterConfirmationHeading: Register participants CourseParticipantsRegisterConfirmInvalid: Invalid confirmation form! @@ -105,9 +106,9 @@ CourseRegistrationFiles: Registration file(s) CourseRegistrationFilesNeedReupload: Registration files need to be reuploaded every time the registration is changed CourseRegistrationFile: Registration file CourseRegistrationArchive: Zip archive of registration files -CourseDeregistrationNoShow: If you deregister from this course “no show” will be recorded as your exam achievement for all exams associated with this course. If you have good reasons why you shold not be held accountable for leaving the course, please contact a course administrator. Course administrators can deregister you without incurring a permanent record. -CourseDeregistrationFromInvisibleCourse: This course is only visible to enrolled participants and applicants. If you deregister now, you will not be able to access the course again! -CourseDeregistrationNoReRegistration: If you deregister from the course now, you will not be able to re-register yourself. +CourseDeregistrationNoShow: If you deregister from this course type “no show” will be recorded as your exam achievement for all exams associated with this course. If you have good reasons why you shold not be held accountable for leaving the course, please contact a course administrator. Course administrators can deregister you without incurring a permanent record. +CourseDeregistrationFromInvisibleCourse: This course type is only visible to enrolled participants and applicants. If you deregister now, you will not be able to access the course type again! +CourseDeregistrationNoReRegistration: If you deregister from the course type now, you will not be able to re-register yourself. LoginNecessary: Please log in first! RegisterRetry: You haven't been enrolled. Press "Enrol for course" to enrol CourseRegisterOk: Successfully enrolled for course @@ -126,9 +127,9 @@ CourseUserExamsResultSet count: Successfully adjusted the participant's result f CourseUserExamResultDoesNotMatchMode examn: The chosen result does not match the grading mode for exam “#{examn}” CourseUserExamsDeregistered count: Successfully deregistered participant from #{show count} #{pluralEN count "exam" "exams"} CourseUserNoExamsDeregistered: Participant is not registered for any of the selected exams -CourseUserTutorialsDeregistered count: Sucessfully deregistered participant from #{show count} #{pluralEN count "tutorial" "tutorials"} -CourseUserNoTutorialsDeregistered: Participant is not registered for any of the selected tutorials -CourseUserTutorials: Registered tutorials +CourseUserTutorialsDeregistered count: Sucessfully deregistered participant from #{show count} #{pluralEN count "course" "courses"} +CourseUserNoTutorialsDeregistered: Participant is not registered for any of the selected courses +CourseUserTutorials: Registered courses CourseUserExams: Registered exams CourseUserSheets: Exercise sheets CsvColumnUserName: Participant's full name @@ -138,62 +139,62 @@ CsvColumnUserBirthday: Birthday CsvColumnUserEmail: Participant's email address CsvColumnUserCourseStudyFeatures: All relevant features of study for the participant, separated by semicolon (;) CsvColumnUserRegistration: Time of participant's enrollment (ISO 8601) -CsvColumnUserTutorial: Tutorials which the user is registered for, separated by semicolon (;). For each registration group among the tutorials there is a separate column. The registration group columns contain at most one tutorial per participant. If every tutorial has a registration group there is no column "tutorial". +CsvColumnUserTutorial: Courses which the user is registered for, separated by semicolon (;). For each registration group among the courses there is a separate column. The registration group columns contain at most one course per participant. If every course has a registration group there is no column "course". CsvColumnUserExam: Exams which the user is registered for, separated by semicolon (;). CsvColumnUserSubmissionGroup: Registered submission group CsvColumnUserSurname: Participant's surname CsvColumnUserFirstName: Participant's given name -CsvColumnUserNote: Course notes for the participant +CsvColumnUserNote: Course type notes for the participant CourseUserCsvName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-participants -CourseUserTutorial: Registered tutorial +CourseUserTutorial: Registered course CourseUserExam: Registered exam CourseUserCsvIncludeSheets: Exercise sheets CourseUserCsvSheetName tid ssh csh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh} Participants CourseUserCsvIncludeSheetsTip: Should the exportet CSV-file additionally contain one column per exercise sheet? RegisteredSince: Enrolled since CourseUserState: State -CourseTutorial: Tutorial +CourseTutorial: Course CourseExam: Exam ExerciseSheet: Exercise sheet CourseUsersDeregistered count: Successfully deregistered #{show count} users from course -CourseUsersTutorialRegistered count: Successfully registered #{show count} users for tutorial +CourseUsersTutorialRegistered count: Successfully registered #{show count} users for course CourseUsersExamRegistered count: Successfully registered #{show count} users for exam CourseUsersSubmissionGroupSetNew count: Successfully added #{show count} #{pluralEN count "user" "users"} to submission group CourseUsersSubmissionGroupUnset count: Successfully removed #{show count} #{pluralEN count "user" "users"} from their #{pluralEN count "submission group" "respective submission groups"} CourseUsersStateSet count: Successfully changed state of #{show count} #{pluralEN count "user" "users"} #templates/course.hamlet -LecturerFor: Lecturer -LecturersFor: Lecturers +LecturerFor: Course administrator +LecturersFor: Course administrators AssistantFor: Assistant AssistantsFor: Assistants CourseAdminFor: Course administration -TutorsFor n: #{pluralEN n "Tutor" "Tutors"} +TutorsFor n: #{pluralENs n "Instructor" } CorrectorsFor n: #{pluralEN n "Corrector" "Correctors"} -CourseParticipantsHeading: Course participants +CourseParticipantsHeading: Course type participants CourseParticipantsCount n: #{n} CourseParticipantsCountOf n m: #{n} of #{m} CourseVisibility: Visibility -CourseInvisible: This course is currently only visible to lecturers, assistants, tutors, correctors, enrolled participants and applicants. +CourseInvisible: This course type is currently only visible to course administrators, assistants, instructors, correctors, enrolled participants and applicants. CourseRegistrationInterval: Enrolment CourseDirectRegistrationInterval: Direct enrolment CourseDeregisterUntil time: Deregistration only until #{time} NotRegistered: Note enrolled for this course CourseMaterial: Material -CourseMaterialNotFree: Course material is only accessible to members of the course, e.g. for participants, tutors, correctors or administratiors. -CourseMaterialsFoundHere: Material for this course is available here -CourseMaterialsNoneVisible: Currently there is no material for this course or only material to which you don't have access (e.g. because of visibility settings) -CourseSheetsFoundHere: Exercise sheets for this course are available here -CourseSheetsNoneVisible: Currently there are no exercise sheets for this course or only exercise sheets to which you don't have access (e.g. because of visibility settings) +CourseMaterialNotFree: Course type material is only accessible to members of the course, e.g. for participants, instructors, correctors or administratiors. +CourseMaterialsFoundHere: Material for this course type is available here +CourseMaterialsNoneVisible: Currently there is no material for this course type or only material to which you don't have access (e.g. because of visibility settings) +CourseSheetsFoundHere: Exercise sheets for this course type are available here +CourseSheetsNoneVisible: Currently there are no exercise sheets for this course type or only exercise sheets to which you don't have access (e.g. because of visibility settings) SheetListCourse: Exercise sheets CourseExams: Exams -CourseTutorials: Tutorials +CourseTutorials: Courses #templates course/user CourseUserCorrections: Submissions CourseSubmissionGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "submission" "submissions"} CourseSingleUserExams: Exams -CourseSingleUserTutorials: Tutorials +CourseSingleUserTutorials: Courses Surname: Surname(s) FirstName: Given name(s) Title: Title @@ -213,7 +214,7 @@ CourseAssistant: Assistant CourseParticipantStateIsInactive: Participant is inactive CourseParticipantStateIsActive: Participant is active CourseUserSendMail: Send message to participant -CourseUserRegisterTutorial: Register tutorial +CourseUserRegisterTutorial: Register course CourseUserRegisterExam: Register exam CourseUserSetSubmissionGroup: Set group-submission CourseUserReRegister: Reregister participant @@ -227,7 +228,7 @@ TutorialRegisterFrom: Register from TutorialRegisterTo: Register to CourseDeleteQuestion: Are you sure you want to delete the below-mentioned course? -CourseDeleted: Course deleted +CourseDeleted: Course type deleted UtilEditedBy name time: #{time} by #{name} CourseDate: Date @@ -242,4 +243,5 @@ CourseAvsRegisterTitle: Register participants CourseAvsRegisterParticipants: Participants CourseAvsRegisterParticipantsTip: Separate multiple participants with comma -CourseQualifications n: Associated #{pluralENs n "Qualification"} \ No newline at end of file +CourseQualifications n: Associated #{pluralENs n "Qualification"} +CourseCertificate course@Text: Certificate of attendance: #{course} \ No newline at end of file diff --git a/messages/uniworx/categories/courses/courses/event/de-de-formal.msg b/messages/uniworx/categories/courses/courses/event/de-de-formal.msg index 1eadb6f31..e6ef8820f 100644 --- a/messages/uniworx/categories/courses/courses/event/de-de-formal.msg +++ b/messages/uniworx/categories/courses/courses/event/de-de-formal.msg @@ -8,17 +8,17 @@ CourseEventTypePlaceholder: Vorlesung, Zentralübung, ... CourseEventTime: Zeit CourseEventRoom: Regulärer Raum CourseEventRoomHidden: Raum nur für Teilnehmer:innen -CourseEventRoomHiddenTip: Soll der Raum nur angemeldeten Kursteilnehmer:innen angezeigt werden? +CourseEventRoomHiddenTip: Soll der Raum nur angemeldeten Kursartteilnehmer:innen angezeigt werden? CourseEventRoomIsUnset !ident-ok: — -CourseEventRoomIsHidden: Raum wird nur Kurs-assoziierten Personen (Teilnehmer:innen, Tutor:innen, Korrektor:innen, etc.) angezeigt +CourseEventRoomIsHidden: Raum wird nur Kursart-assoziierten Personen (Teilnehmer:innen, Ausbilder:innen, Korrektor:innen, etc.) angezeigt CourseEventNote: Notiz CourseEventActions: Aktionen CourseEventsActionEdit: Bearbeiten CourseEventsActionDelete: Löschen CourseEventsActionCreate: Neuer Termin -CourseEventCreated: Kurstermin erfolgreich angelegt -CourseEventEdited: Kurstermin erfolgreich editiert +CourseEventCreated: Kursarttermin erfolgreich angelegt +CourseEventEdited: Kursarttermin erfolgreich editiert CourseEventDeleteQuestion: Wollen Sie den unten aufgeführten Termin wirklich löschen? -CourseEventDeleted: Kurstermin erfolgreich gelöscht -CourseEventNew: Neuer Kurstermin -CourseEventEdit: Kurstermin bearbeiten \ No newline at end of file +CourseEventDeleted: Kursarttermin erfolgreich gelöscht +CourseEventNew: Neuer Kursarttermin +CourseEventEdit: Kursarttermin bearbeiten \ No newline at end of file diff --git a/messages/uniworx/categories/courses/courses/event/en-eu.msg b/messages/uniworx/categories/courses/courses/event/en-eu.msg index 247dc85d1..0984a73c0 100644 --- a/messages/uniworx/categories/courses/courses/event/en-eu.msg +++ b/messages/uniworx/categories/courses/courses/event/en-eu.msg @@ -8,17 +8,17 @@ CourseEventTypePlaceholder: Lecture, Exercise discussion, ... CourseEventTime: Time CourseEventRoom: Regular room CourseEventRoomHidden: Room only for participants -CourseEventRoomHiddenTip: Should the room only be displayde to course participants? +CourseEventRoomHiddenTip: Should the room only be displayde to course type participants? CourseEventRoomIsUnset: — -CourseEventRoomIsHidden: Room is only displayed to course associated persons (participants, tutor, correctors, etc.) +CourseEventRoomIsHidden: Room is only displayed to course type associated persons (participants, instructors, correctors, etc.) CourseEventNote: Note CourseEventActions: Actions CourseEventsActionEdit: Edit CourseEventsActionDelete: Delete CourseEventsActionCreate: New occurrence -CourseEventCreated: Successfully created course occurrence -CourseEventEdited: Successfully edited course occurrence -CourseEventDeleteQuestion: Are you sure you want to delete the course occurrence mentioned below? -CourseEventDeleted: Successfully deleted course occurrence -CourseEventEdit: Edit course occurrence -CourseEventNew: New course occurrence \ No newline at end of file +CourseEventCreated: Successfully created course type occurrence +CourseEventEdited: Successfully edited course type occurrence +CourseEventDeleteQuestion: Are you sure you want to delete the course type occurrence mentioned below? +CourseEventDeleted: Successfully deleted course type occurrence +CourseEventEdit: Edit course type occurrence +CourseEventNew: New course type occurrence \ No newline at end of file diff --git a/messages/uniworx/categories/courses/courses/news/de-de-formal.msg b/messages/uniworx/categories/courses/courses/news/de-de-formal.msg index 8322c86db..8ab86d016 100644 --- a/messages/uniworx/categories/courses/courses/news/de-de-formal.msg +++ b/messages/uniworx/categories/courses/courses/news/de-de-formal.msg @@ -13,13 +13,13 @@ CourseNewsVisibleFromEditWarning: Das Datum der Veröffentlichung liegt in der V CourseNewsVisibleFromTip: Ohne Datum nie sichtbar für Teilnehmer:innen; leer lassen ist nur sinnvoll für noch unfertige Nachrichten CourseNewsTitle: Titel CourseNewsSummary: Zusammenfassung -CourseNewsSummaryTip: Wenn angegeben, wird auf der Kursübersichtsseite, platzsparend, nur die Zusammenfassung angezeigt und der Inhalt in ein Popup ausgelagert +CourseNewsSummaryTip: Wenn angegeben, wird auf der Kursartübersichtsseite, platzsparend, nur die Zusammenfassung angezeigt und der Inhalt in ein Popup ausgelagert CourseNewsContent: Inhalt -CourseNewsParticipantsOnly: Nur für Kursteilnehmer:innen +CourseNewsParticipantsOnly: Nur für Kursartteilnehmer:innen CourseNewsVisibleFrom: Sichtbar ab -CourseNewsCreated: Kursnachricht erfolgreich angelegt -CourseNewsEdited: Kursnachricht erfolgreich editiert +CourseNewsCreated: Kursartnachricht erfolgreich angelegt +CourseNewsEdited: Kursartnachricht erfolgreich editiert CourseNewsDeleteQuestion: Wollen Sie die unten aufgeführte Nachricht wirklich löschen? -CourseNewsDeleted: Kursnachricht erfolgreich gelöscht -CourseNewsNew: Neue Kursnachricht -CourseNewsEdit: Kursnachricht bearbeiten \ No newline at end of file +CourseNewsDeleted: Kursartnachricht erfolgreich gelöscht +CourseNewsNew: Neue Kursartnachricht +CourseNewsEdit: Kursartnachricht bearbeiten \ No newline at end of file diff --git a/messages/uniworx/categories/courses/courses/news/en-eu.msg b/messages/uniworx/categories/courses/courses/news/en-eu.msg index 27a89b928..e1a0297a6 100644 --- a/messages/uniworx/categories/courses/courses/news/en-eu.msg +++ b/messages/uniworx/categories/courses/courses/news/en-eu.msg @@ -9,17 +9,17 @@ CourseNewsLastEdited time: Last changed: #{time} CourseNewsActionEdit: Edit CourseNewsActionDelete: Delete CourseNewsActionCreate: Create new item -CourseNewsVisibleFromEditWarning: This item of course news has already been published and should no longer be changed sind this might confuse participants. +CourseNewsVisibleFromEditWarning: This item of course type news has already been published and should no longer be changed sind this might confuse participants. CourseNewsVisibleFromTip: If left empty this item is never visible. Leave empty for unfinished items CourseNewsTitle: Title CourseNewsSummary: Summary -CourseNewsSummaryTip: If specified this only the summary will be shown on the course page, saving space. The content will be shown in a popup +CourseNewsSummaryTip: If specified this only the summary will be shown on the course type page, saving space. The content will be shown in a popup CourseNewsContent: Content -CourseNewsParticipantsOnly: Only for course participants +CourseNewsParticipantsOnly: Only for course type participants CourseNewsVisibleFrom: Visible from -CourseNewsCreated: Successfully created item of course news -CourseNewsEdited: Successfully edited item of course news -CourseNewsDeleteQuestion: Are you sure you want to delete the item of course news listed below? -CourseNewsDeleted: Successfully deleted item of course news -CourseNewsNew: Add course news -CourseNewsEdit: Edit item of course news +CourseNewsCreated: Successfully created item of course type news +CourseNewsEdited: Successfully edited item of course type news +CourseNewsDeleteQuestion: Are you sure you want to delete the item of course type news listed below? +CourseNewsDeleted: Successfully deleted item of course type news +CourseNewsNew: Add course type news +CourseNewsEdit: Edit item of course type news diff --git a/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg b/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg index acd288c69..bd87559c7 100644 --- a/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg +++ b/messages/uniworx/categories/courses/exam/exam/de-de-formal.msg @@ -5,13 +5,13 @@ ExamRegistrationInviteDeadline: Einladung nur gültig bis ExamRegistrationEnlistDirectly: Bekannte Nutzer:innen sofort als Teilnehmer:innen eintragen ExamRegistrationEnlistDirectlyTip: Sollen, wenn manche der E-Mail-Adressen bereits in Uni2work mit Nutzer:innen assoziiert sind, jene Nutzer:innen direkt zur Prüfung hinzugefügt werden? Ansonsten werden Einladung an alle E-Mail-Adressen (nicht nur unbekannte) versandt, die die Nutzer:innen zunächst akzeptieren müssen um Prüfungsteilnehmer:in zu werden. -ExamRegistrationRegisterCourse: Nutzer:in auch zum Kurs anmelden -ExamRegistrationRegisterCourseTip: Nutzer:innen, die keine Kursteilnehmer:innen sind, werden sonst nicht zur Prüfung angemeldet. +ExamRegistrationRegisterCourse: Nutzer:in auch zur Kursart anmelden +ExamRegistrationRegisterCourseTip: Nutzer:innen, die keine Kursartteilnehmer:innen sind, werden sonst nicht zur Prüfung angemeldet. ExamRegistrationInviteField: Einzuladende E-Mail-Adressen ExamParticipantsRegisterHeading: Prüfungsteilnehmer:in hinzufügen ExamParticipantsInvited n@Int: #{n} #{pluralDE n "Einladung" "Einladungen"} per E-Mail verschickt -ExamRegistrationAndCourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} #{pluralDE n "wurde" "wurden"} sowohl zum Kurs, als auch zur Prüfung angemeldet -ExamRegistrationNotRegisteredWithoutCourse n@Int: #{n} #{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} #{pluralDE n "wurde" "wurden"} nicht zur Prüfung angemeldet, da #{pluralDE n "er/sie" "sie"} nicht zum Kurs angemeldet #{pluralDE n "ist" "sind"} +ExamRegistrationAndCourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} #{pluralDE n "wurde" "wurden"} sowohl zur Kursart, als auch zur Prüfung angemeldet +ExamRegistrationNotRegisteredWithoutCourse n@Int: #{n} #{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} #{pluralDE n "wurde" "wurden"} nicht zur Prüfung angemeldet, da #{pluralDE n "er/sie" "sie"} nicht zur Kursart angemeldet #{pluralDE n "ist" "sind"} ExamAutoOccurrenceMinimizeRooms: Verwendete Räume/Termine minimieren ExamAutoOccurrenceMinimizeRoomsTip: Soll, für die Aufteilung, die Liste an Räumen/Terminen zunächst reduziert werden, sodass nur so wenige Räume verwendet werden, wie nötig (größte zuerst)? ExamAutoOccurrenceOccurrencesChangedInFlight: Raumliste wurde verändert @@ -48,7 +48,7 @@ ExamVisibleFrom: Sichtbar ab ExamVisibleFromTip: Ohne Datum nie sichtbar und keine Anmeldung möglich ExamRegisterFrom: Anmeldung ab ExamRegisterTo: Anmeldung bis -ExamRegisterFromTip: Zeitpunkt ab dem sich Kursteilnehmer:innen selbständig zur Prüfung anmelden können; ohne Datum ist keine Anmeldung möglich +ExamRegisterFromTip: Zeitpunkt ab dem sich Kursartteilnehmer:innen selbständig zur Prüfung anmelden können; ohne Datum ist keine Anmeldung möglich ExamDeregisterUntil: Abmeldung bis ExamPublishOccurrenceAssignments: Termin- bzw. Raumzuteilung den Teilnehmer:innen mitteilen um ExamPublishOccurrenceAssignmentsTip: Ab diesem Zeitpunkt können Teilnehmer:innen einsehen zu welcher Teilprüfung bzw. welchen Raum sie angemeldet sind @@ -66,8 +66,8 @@ ExamGradingMode: Bewertungsmodus ExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen? ExamStaff: Prüfer:innen/Verantwortliche Hochschullehrer:innen ExamStaffTip: Geben Sie bitte in jedem Fall einen Namen an, der Prüfer:in/Veranstalter:in/Hochschullehrer:in eindeutig identifiziert! Sollte der Name des Prüfers/der Prüferin allein womöglich nicht eindeutig sein, so geben Sie bitte eindeutig identifizierende Zusatzinfos, wie beispielsweise den Lehrstuhl bzw. die LFE o.Ä., an. -ExamExamOfficeSchools: Zusätzliche Institute -ExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Instituten, die Sie hier angeben, erhalten im System (zusätzlich zum primären Institut des zugehörigen Kurses) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen. +ExamExamOfficeSchools: Zusätzliche Bereiche +ExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Bereichen, die Sie hier angeben, erhalten im System (zusätzlich zum primären Bereich der zugehörigen Kursart) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen. ExamCorrectorEmail: E-Mail ExamCorrectors: Korrektor:innen ExamCorrectorsTip: Hier eingetragene Korrektor:innen können zwischen Beginn der Prüfung und "Bewertung abgeschlossen ab" Ergebnisse für alle Teilprüfungen und alle Teilnehmer:innen im System hinterlegen. @@ -126,10 +126,10 @@ ExamOccurrenceDuplicateName eoName@ExamOccurrenceName: Interne Terminbezeichnung ExamOccurrenceRoomIsUnset !ident-ok: — ExamOccurrenceRoomIsHidden: Raum wird nur Teilnehmer:innen angezeigt ExamOccurrenceCannotBeDeletedDueToRegistrations eoName@ExamOccurrenceName: Termin #{eoName} kann nicht gelöscht werden, da noch Teilnehmer:innen diesem Termin zugewiesen sind. Über die Liste von Prüfungsteilnehmern können Sie zunächst die entsprechenden Terminzuweisungen entfernen. -ExamRegistrationMustFollowSchoolSeparationFromStart dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Beginn" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen. -ExamRegistrationMustFollowSchoolDuration dayCount@Int: Nach Regeln des Instituts #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Anmeldung bis" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen. -ExamModeRequiredForRegistration: Nach Regeln des Institus muss die "Ausgestaltung der Prüfung" vollständig angegeben sein, bevor "Anmeldung ab" festgelegt werden kann. -ExamModeSchoolDiscouraged: Nach Regeln des Instituts wird von der angegebenen "Ausgestaltung der Prüfung" abgeraten +ExamRegistrationMustFollowSchoolSeparationFromStart dayCount@Int: Nach Regeln des Bereichs #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Beginn" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen. +ExamRegistrationMustFollowSchoolDuration dayCount@Int: Nach Regeln des Bereichs #{pluralDE dayCount "muss" "müssen"} zwischen "Anmeldung ab" und "Anmeldung bis" mindestens #{dayCount} #{pluralDE dayCount "Tag" "Tage"} liegen. +ExamModeRequiredForRegistration: Nach Regeln des Bereichs muss die "Ausgestaltung der Prüfung" vollständig angegeben sein, bevor "Anmeldung ab" festgelegt werden kann. +ExamModeSchoolDiscouraged: Nach Regeln des Bereichs wird von der angegebenen "Ausgestaltung der Prüfung" abgeraten ExamStaffRequired: „Prüfer:innen/Verantwortilche Hochschullehrer:innen” muss angegeben werden ExamNotRegistered: Nicht zur Prüfung angemeldet ExamRegistered: Zur Prüfung angemeldet @@ -144,7 +144,7 @@ ExamRegistrationInviteExplanation: Sie wurden eingeladen, Prüfungsteilnehmer:in ExamUnauthorizedParticipant: Angegebener Benutzer/angegebene Benutzerin ist nicht als Teilnehmer:in dieser Veranstaltung registriert. ExamRegistrationInvitationAccepted examn@ExamName: Sie wurden als Teilnehmer:in für #{examn} eingetragen ExamFinishedParticipant: Bewertung voraussichtlich abgeschlossen -ExamLoginToRegister: Um sich zum Kurs anzumelden müssen Sie zunächst in Uni2work anmelden +ExamLoginToRegister: Um sich zur Kursart anzumelden müssen Sie zunächst in Uni2work anmelden ExamRegisterForOccurrence: Anmeldung zur Prüfung erfolgt durch Anmeldung zu einem Termin/Raum ExamShowIdentificationRequired: Prüfungsteilnehmer:innen müssen sich ausweisen können. Halten Sie dafür einen amtlichen Lichtbildausweis (Personalausweis, Reisepass, Aufenthaltstitel) und Ihren Studierendenausweis bereit. CsvColumnExamUserSurname: Nachname(n) des Teilnehmers/der Teilnehmerin @@ -271,7 +271,7 @@ ExamEditWouldBreakSheetTypeReference: Durch Ihre Änderungen würde ein Prüfung ExamEditExamNameTaken exam@ExamName: Es existiert bereits eine Prüfung mit Namen #{exam} Date: Datum -ExamRegistrationRegisteredWithoutField n@Int: #{n} #{pluralDE n "Teilnehmer:in wurde" "wurden"} sowohl zur Prüfung, als auch #{pluralDE n "Teilnehmer:innen ohne assoziiertes Studienfach" "ohne assoziierte Studienfächer"} zum Kurs angemeldet, da #{pluralDE n "kein eindeutiges Hauptfach bestimmt werden konnte" "keine eindeutigen Hauptfächer bestimmt werden konnten"} +ExamRegistrationRegisteredWithoutField n@Int: #{n} #{pluralDE n "Teilnehmer:in wurde" "wurden"} sowohl zur Prüfung, als auch #{pluralDE n "Teilnehmer:innen ohne assoziiertes Studienfach" "ohne assoziierte Studienfächer"} zur Kursart angemeldet, da #{pluralDE n "kein eindeutiges Hauptfach bestimmt werden konnte" "keine eindeutigen Hauptfächer bestimmt werden konnten"} ExamRegistrationParticipantsRegistered n@Int: #{n} #{pluralDE n "Teilnehmer:in wurde" "Teilnehmer:innen wurden"} zur Prüfung angemeldet ExamOpenBook: Open Book ExamClosedBook: Closed Book @@ -295,7 +295,7 @@ ExamUserSetPartResult: Teilergebnis setzen ExamUserSetBonus: Bonuspunkte setzen ExamUserSetResult: Prüfungsergebnis setzen ExamUserMarkSynchronised: Prüfungsleistung als synchronisiert markieren -ExamUserCsvCourseRegister: Benutzer:in zum Kurs und zur Prüfung anmelden +ExamUserCsvCourseRegister: Benutzer:in zur Kursart und zur Prüfung anmelden ExamUserCsvRegister: Kursteilnehmer:in zur Prüfung anmelden ExamUserCsvAssignOccurrence: Teilnehmer:innen einen anderen Termin/Raum zuweisen ExamUserCsvDeregister: Teilnehmer:in von der Prüfung abmelden @@ -320,6 +320,6 @@ ExamFinished: Ergebnisse sichtbar ab ExamAuthorshipStatementSection: Eigenständigkeitserklärung ExamAuthorshipStatementRequired: Eigenständigkeitserklärung für prüfungszugehörige Übungsblattabgaben einfordern? ExamAuthorshipStatementRequiredTip: Sollen für alle zu dieser Prüfung zugehörige Übungsblätter die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert werden, eine Eigenständigkeitserklärung zu akzeptieren? -ExamAuthorshipStatementRequiredForcedTip: Für dieses Institut ist vorgeschrieben, dass für alle zu diese Prüfung zugehörigen Übungsblätter die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert werden, eine Eigenständigkeitserklärung zu akzeptieren. +ExamAuthorshipStatementRequiredForcedTip: Für diesen Bereich ist vorgeschrieben, dass für alle zu diese Prüfung zugehörigen Übungsblätter die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert werden, eine Eigenständigkeitserklärung zu akzeptieren. ExamAuthorshipStatementContent: Eigenständigkeitserklärung -ExamAuthorshipStatementContentForcedTip: Für dieses Institut ist die institutsweit vorgegebene Eigenständigkeitserklärung für prüfungsrelevante Übungsblätter zu verwenden. Benutzerdefinierte Erklärungen sind nicht gestattet. Für alle zu diese Prüfung zugehörigen Übungsblätter werden die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert, diese Eigenständigkeitserklärung zu akzeptieren. \ No newline at end of file +ExamAuthorshipStatementContentForcedTip: Für diesen Bereich ist die bereichsweit vorgegebene Eigenständigkeitserklärung für prüfungsrelevante Übungsblätter zu verwenden. Benutzerdefinierte Erklärungen sind nicht gestattet. Für alle zu diese Prüfung zugehörigen Übungsblätter werden die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert, diese Eigenständigkeitserklärung zu akzeptieren. \ No newline at end of file diff --git a/messages/uniworx/categories/courses/exam/exam/en-eu.msg b/messages/uniworx/categories/courses/exam/exam/en-eu.msg index bf2f792c3..32ffda98e 100644 --- a/messages/uniworx/categories/courses/exam/exam/en-eu.msg +++ b/messages/uniworx/categories/courses/exam/exam/en-eu.msg @@ -5,7 +5,7 @@ ExamRegistrationInviteDeadline: Invitation valid until ExamRegistrationEnlistDirectly: Register known users directly ExamRegistrationEnlistDirectlyTip: Should users whose email addresses are known to the system be registered for the exam directly? Otherwise invitations will be sent to alle users, which they will have to accept first in order to be registered. Unknown users always receive an invitation. -ExamRegistrationRegisterCourse: Also enroll users in course +ExamRegistrationRegisterCourse: Also enroll users in course type ExamRegistrationRegisterCourseTip: Users that aren't enrolled already won't be registered for the exam otherwise. ExamRegistrationInviteField: Email addresses ExamParticipantsRegisterHeading: Add exam participants @@ -45,10 +45,10 @@ ExamStart: Start ExamEnd: End ExamTimeTip: Only for informational purposes. The actual times are set for each occurrence/room ExamVisibleFrom: Visible from -ExamVisibleFromTip: If left empty the exam is never visible and course participants may not register. +ExamVisibleFromTip: If left empty the exam is never visible and course type participants may not register. ExamRegisterFrom: Register from ExamRegisterTo: Register to -ExamRegisterFromTip: Start of the period in which course participants may register themselves for the exam. If left empty participants are never allowed to register. +ExamRegisterFromTip: Start of the period in which course type participants may register themselves for the exam. If left empty participants are never allowed to register. ExamDeregisterUntil: Deregister until ExamPublishOccurrenceAssignments: Publish occurrence/room-assignments ExamPublishOccurrenceAssignmentsTip: At this time participants can find out to which occurrence/room they are assigned @@ -159,7 +159,7 @@ CsvColumnExamUserExercisePassesMax: Maximum number of exercise sheets the partic CsvColumnExamUserBonus: Exam bonus points CsvColumnExamUserParts: Number of points the participant achieved per exam part. One column per exam part if applicable. CsvColumnExamUserResult: Exam achievement; "passed", "failed", "no-show", "voided", or any number grade ("1.0", "1.3", "1.7", ..., "4.0", "5.0") -CsvColumnExamUserCourseNote: Course notes for the participant +CsvColumnExamUserCourseNote: Course type notes for the participant CsvColumnExamOfficeExamUserOccurrenceStart: Exam occurrence (ISO 8601) CsvColumnUserStudyFeatures: All relevant features of study for the participant, separated by semicolon (;) ExamUserCsvName tid ssh csh examn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase examn}-participants @@ -176,7 +176,7 @@ ExamAction: Action ExamUsersExamDataRequiresRegistration: If exam data (part-/result, occurrence/room, bonus) is to be modified/set, the relenvant participant needs to be registered for the exam. ExamNoOccurrence: No occurrence/room ExamBonusNone: No bonus points -ExamUserCsvCourseNoteDeleted: Course note will be deleted +ExamUserCsvCourseNoteDeleted: Course type note will be deleted ExamUsersDeregistered count: Successfully deregistered #{show count} #{pluralEN count "participant" "participants"} ExamUsersOccurrenceUpdated count: Successfully assigned occurrence/room for #{show count} #{pluralEN count "participant" "participants"} ExamUsersResultsAccepted count: Successfully accepted computed result for #{show count} #{pluralEN count "participant" "participants"} @@ -302,9 +302,9 @@ ExamUserCsvOverrideResult: Override exam result in contradiction of computed val ExamUserCsvSetBonus: Set bonus points ExamUserCsvSetResult: Set exam result ExamUserCsvSetPartResult: Set result for exam part -ExamUserCsvSetCourseNote: Modify course participant notes -ExamUserCsvExceptionNoMatchingUser: Course participant could not be identified uniquely. All identifiers (given name(s), surname, display name, matriculation, ..) must match exactly. You can try to remove some of the identifiers for the given line (i.e. all but matriculation). Uni2work will then search for users using only the remaining identifiers. In this case special care should be taken that Uni2work correctly identifies the intended user. -ExamUserCsvExceptionMultipleMatchingUsers: Course participant could not be identified uniquely. There are multiple users that match the given identifiers. You can try to add more identifiers for the given line to ensure that only the intended user can be identified with them. +ExamUserCsvSetCourseNote: Modify course type participant notes +ExamUserCsvExceptionNoMatchingUser: Course type participant could not be identified uniquely. All identifiers (given name(s), surname, display name, matriculation, ..) must match exactly. You can try to remove some of the identifiers for the given line (i.e. all but matriculation). Uni2work will then search for users using only the remaining identifiers. In this case special care should be taken that Uni2work correctly identifies the intended user. +ExamUserCsvExceptionMultipleMatchingUsers: Course type participant could not be identified uniquely. There are multiple users that match the given identifiers. You can try to add more identifiers for the given line to ensure that only the intended user can be identified with them. ExamUserCsvExceptionNoMatchingStudyFeatures: The specified field did not match with any of the participant's fields of study. You can try to remove the field of study for the given line. Uni2work will then automatically choose a field of study. ExamUserCsvExceptionNoMatchingOccurrence: Occurrence/room could not be identified uniquely. Please ensure that the given line only contains internal room identifiers exactly as they have been configured for this exam. ExamUserCsvExceptionMismatchedGradingMode expectedGradingMode actualGradingMode: The imported data contained an exam achievement which does not match the grading mode for this exam. The expected grading mode can be changed at "Edit exam" ("Passed/Failed", "Numeric grades", or "Mixed"). diff --git a/messages/uniworx/categories/courses/exam/exam_office/de-de-formal.msg b/messages/uniworx/categories/courses/exam/exam_office/de-de-formal.msg index 797c9bbe9..a949e4819 100644 --- a/messages/uniworx/categories/courses/exam/exam_office/de-de-formal.msg +++ b/messages/uniworx/categories/courses/exam/exam_office/de-de-formal.msg @@ -25,7 +25,7 @@ InvalidExamOfficeFieldMode parseErr@Text: Konnte „#{parseErr}“ nicht interpr TransactionExamOfficeFieldsUpdated nUpdates@Int: #{nUpdates} #{pluralDE nUpdates "Studienfach" "Studienfächer"} angepasst HeadingExamOfficeFields: Fächer HeadingExamOfficeUsers: Benutzer:innen -ExamOfficeSubscribedFieldsExplanation: Sie können für alle Benutzer:innen, die mindestens eines der angegeben Studienfächer studieren, sämtliche Prüfungsergebnisse einsehen. Sie haben zusätzlich die Möglichkeit anzugeben, ob es den Benutzer:innen gestattet sein soll, dieser Einsicht im Einzelfall (pro Kurs) zu widersprechen. +ExamOfficeSubscribedFieldsExplanation: Sie können für alle Benutzer:innen, die mindestens eines der angegeben Studienfächer studieren, sämtliche Prüfungsergebnisse einsehen. Sie haben zusätzlich die Möglichkeit anzugeben, ob es den Benutzer:innen gestattet sein soll, dieser Einsicht im Einzelfall (pro Kursart) zu widersprechen. MailSubjectExamOfficeUserInvitation displayName@Text: Berücksichtigung von Prüfungsleistungen in Uni2work ExamOfficeUserInviteHeading displayName@Text: Zugriff auf Ihre Prüfungsleistungen durch #{displayName} ExamOfficeUserInviteExplanation: Um Ihre Prüfungsleistungen ordnungsgemäß anrechnen zu können (z.B. im finalen Transcript of Records für Erasmus-Studierende) werden sie eingeladen der hierfür zuständigen Stelle Einsicht zu gewähren. @@ -49,7 +49,7 @@ ExamFinishedSince time@Text: Prüfungsergebnisse sichtbar seit #{time} #templates exam-office/* ExamUserSyncOfficeName !ident-ok: Name ExamUserSyncTime: Zeitpunkt -ExamUserSyncSchools: Institute +ExamUserSyncSchools: Bereiche ExamUserSyncLastChange: Zuletzt geändert ExamTimes: Termine diff --git a/messages/uniworx/categories/courses/exam/external_exam/de-de-formal.msg b/messages/uniworx/categories/courses/exam/external_exam/de-de-formal.msg index f53348ecb..2f22aa6b6 100644 --- a/messages/uniworx/categories/courses/exam/external_exam/de-de-formal.msg +++ b/messages/uniworx/categories/courses/exam/external_exam/de-de-formal.msg @@ -15,13 +15,13 @@ ExternalExamCorrectErrorNeedleTooShort: Dieser Identifikator ist zu kurz. UnauthorizedExternalExamCorrectorGrade: Sie haben nicht die Berechtigung für diese Prüfung Gesamtergebnisse einzutragen. ExternalExamCorrectErrorMultipleMatchingUsers: Dem Identifikator konnten mehrere Studierende zugeordnet werden. ExternalExamCorrectErrorNoMatchingUsers: Dem Identifikator konnte kein Studierender zugeordnet werden. -ExternalExamEdited coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kurs „#{coursen}“ erfolgreich bearbeitet. -ExternalExamExists coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kurs „#{coursen}“ existiert bereits. +ExternalExamEdited coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kursart „#{coursen}“ erfolgreich bearbeitet. +ExternalExamExists coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kursart „#{coursen}“ existiert bereits. ExternalExamEdit coursen@CourseName examn@ExamName: Bearbeiten: #{coursen}, #{examn} -ExternalExamSemester !ident-ok: Semester -ExternalExamSchool: Institut +ExternalExamSemester !ident-ok: Jahr +ExternalExamSchool: Bereich ExternalExamCourseName: Veranstaltung -ExternalExamCourseNameTip: Muss nur innerhalb von Semester und Institut eindeutig sein. +ExternalExamCourseNameTip: Muss nur innerhalb von Jahr und Bereich eindeutig sein. ExternalExamCourseNamePlaceholder: Analysis I, Programmierung und Modellierung, ... ExternalExamExamName: Prüfung ExternalExamExamNameTip: Muss innerhalb der Veranstaltung eindeutig sein. @@ -31,8 +31,8 @@ ExternalExamDefaultTimePlaceholder: Zeitpunkt ExternalExamDefaultTimeTip: Der Zeitpunkt zu dem die Prüfung abgelegt wurde, muss pro Teilnehmer:in festgelegt werden. Der hier angegebene Zeitpunkt wird als Standardwert für Teilnehmer:innen verwendet, bei denen später nicht ein abweichender Zeitpunkt angegeben wird. ExternalExamGradingMode: Bewertungsmodus ExternalExamGradingModeTip: In welcher Form werden Prüfungsleistungen für diese Prüfung eingetragen? -ExternalExamExamOfficeSchools: Zusätzliche Institute -ExternalExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Instituten, die Sie hier angeben, erhalten im System (zusätzlich zum angegebenen primären Institut) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen. +ExternalExamExamOfficeSchools: Zusätzliche Bereiche +ExternalExamExamOfficeSchoolsTip: Prüfungsbeauftragte von Bereichen, die Sie hier angeben, erhalten im System (zusätzlich zum angegebenen primären Bereich) volle Einsicht in sämtliche für diese Prüfung hinterlegten Leistungen, unabhängig von den Studiendaten der Teilnehmer:innen. ExternalExamStaffInviteHeading coursen@CourseName examn@ExamName: Einladung zum Prüfer/zur Prüferin für „#{examn}“ in „#{coursen}“ ExternalExamStaffInviteExplanation: Sie wurden eingeladen als Prüfer:in für eine Uni2work-externe Prüfung zu wirken. Sie können dann u.A. Noten für die Prüfung hinterlegen. ExternalExamStaffInvitationAccepted coursen@CourseName examn@ExamName: Sie sind nun als Prüfer:in für „#{examn}“ in „#{coursen}“ eingetragen. @@ -41,10 +41,10 @@ ExternalExamStaffTip: Assoziierte Personen werden den Prüfungsbeauftragten und ExternalExamStaffAlreadyAdded: Person wurde bereits der Prüfung hinzugefügt ExternalExamStaffEmail: E-Mail ExternalExamUserMustBeStaff: Sie selbst müssen stets assoziierte Person sein, für die externen Prüfungen, die Sie anlegen -ExternalExamCourseExists: Der angegebene Kurs existiert im System. Prüfungen sollten daher direkt beim Kurs (statt extern) hinterlegt werden. +ExternalExamCourseExists: Die angegebene Kursart existiert im System. Prüfungen sollten daher direkt bei der Kursart (statt extern) hinterlegt werden. HeadingExternalExamList: Externe Prüfungen HeadingExternalExamNew: Neue externe Prüfung -ExternalExamCreated coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kurs „#{coursen}“ erfolgreich angelegt. +ExternalExamCreated coursen@CourseName examn@ExamName: Prüfung „#{examn}“ für Kursart „#{coursen}“ erfolgreich angelegt. MailSubjectExternalExamStaffInvitation coursen@CourseName examn@ExamName: Einladung zum Prüfer/zur Prüferin für „#{examn}“ in „#{coursen}“ ExternalExamOccurrenceEdited count@Int64: #{count} #{pluralDE count "Termin" "Termine"} editiert ExternalExamResultEdited count@Int64: #{count} #{pluralDE count "Prüfungsergebnis" "Prüfungsergebnisse"} editiert diff --git a/messages/uniworx/categories/courses/exam/external_exam/en-eu.msg b/messages/uniworx/categories/courses/exam/external_exam/en-eu.msg index a496ae8f6..933b7acbc 100644 --- a/messages/uniworx/categories/courses/exam/external_exam/en-eu.msg +++ b/messages/uniworx/categories/courses/exam/external_exam/en-eu.msg @@ -15,13 +15,13 @@ ExternalExamCorrectErrorNeedleTooShort: This identifier is too short. UnauthorizedExternalExamCorrectorGrade: You may not enter overall exam achievements for this exam. ExternalExamCorrectErrorMultipleMatchingUsers: This identifier matches on multiple students. ExternalExamCorrectErrorNoMatchingUsers: This identifier does not match any student. -ExternalExamEdited coursen@CourseName examn@ExamName: Succesfully edited exam “#{examn}” for course “#{coursen}”. -ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course “#{coursen}”. +ExternalExamEdited coursen@CourseName examn@ExamName: Succesfully edited exam “#{examn}” for course type “#{coursen}”. +ExternalExamExists coursen@CourseName examn@ExamName: Exam “#{examn}” already exists for course type “#{coursen}”. ExternalExamEdit coursen examn: Edit: #{coursen}, #{examn} -ExternalExamSemester: Semester +ExternalExamSemester: Year ExternalExamSchool: Department ExternalExamCourseName: Course -ExternalExamCourseNameTip: Needs only be unique among within semester and department. +ExternalExamCourseNameTip: Needs only be unique among within year and department. ExternalExamCourseNamePlaceholder: Analysis I, Programming and Modelling, ... ExternalExamExamName: Exam title ExternalExamExamNameTip: Needs only be unique within the course. @@ -34,17 +34,17 @@ ExternalExamGradingModeTip: In which format should grades for this exam be enter ExternalExamExamOfficeSchools: Additional departments ExternalExamExamOfficeSchoolsTip: Exam offices of departments you specify here will also have full access to all results for this exam disregarding the individual participants' features of study. ExternalExamStaffInviteHeading coursen examn: Invitation to act as examiner for “#{examn}” of “#{coursen}” -ExternalExamStaffInviteExplanation: You have been invited to act as an examiner for a uni2work-external exam. After accepting you will be able to upload exam results. +ExternalExamStaffInviteExplanation: You have been invited to act as an examiner for a FRADrive-external exam. After accepting you will be able to upload exam results. ExternalExamStaffInvitationAccepted coursen examn: You are now registered as an examiner for “#{examn}” of “#{coursen}”. ExternalExamStaff: Associated persons ExternalExamStaffTip: The list of ssociated persons is shown to exam offices and participants. Additionally associated persons may upload results for the exam. ExternalExamStaffAlreadyAdded: Person is already associated with the exam. ExternalExamStaffEmail: Email ExternalExamUserMustBeStaff: You yourself must always be an associated person for exams you create. -ExternalExamCourseExists: This course already exists with uni2work. Exams for courses that exist within uni2work should be associated with the course directly instead of being created as an external exam. +ExternalExamCourseExists: This course type already exists with FRADrive. Exams for courses that exist within FRADrive should be associated with the course type directly instead of being created as an external exam. HeadingExternalExamList: External exams HeadingExternalExamNew: New external exam -ExternalExamCreated coursen@CourseName examn@ExamName: Succesfully created exam “#{examn}” for course “#{coursen}”. +ExternalExamCreated coursen@CourseName examn@ExamName: Succesfully created exam “#{examn}” for course type “#{coursen}”. MailSubjectExternalExamStaffInvitation coursen examn: Invitation to act as examiner for “#{examn}” of “#{coursen}” ExternalExamOccurrenceEdited count: Successfully edited #{count} #{pluralEN count "occurrence" "occurrences"} ExternalExamResultEdited count: Successfully edited #{count} #{pluralEN count "exam result" "exam results"} diff --git a/messages/uniworx/categories/courses/material/de-de-formal.msg b/messages/uniworx/categories/courses/material/de-de-formal.msg index f716ff594..92427fff9 100644 --- a/messages/uniworx/categories/courses/material/de-de-formal.msg +++ b/messages/uniworx/categories/courses/material/de-de-formal.msg @@ -21,8 +21,8 @@ MaterialNewHeading: Neues Material veröffentlichen MaterialNewTitle: Neues Material MaterialEditHeading materialName@MaterialName: Material "#{materialName}" editieren MaterialEditTitle materialName@MaterialName: Material "#{materialName}" editieren -MaterialSaveOk tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Material "#{materialName}" erfolgreich gespeichert in Kurs #{tid}-#{ssh}-#{csh} -MaterialNameDup tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Es gibt bereits Material mit Namen "#{materialName}" in diesem Kurs #{tid}-#{ssh}-#{csh} +MaterialSaveOk tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Material "#{materialName}" erfolgreich gespeichert in Kursart #{tid}-#{ssh}-#{csh} +MaterialNameDup tid@TermId ssh@SchoolId csh@CourseShorthand materialName@MaterialName: Es gibt bereits Material mit Namen "#{materialName}" in dieser Kursart #{tid}-#{ssh}-#{csh} MaterialDeleteCaption: Wollen Sie das unten aufgeführte Material wirklich löschen? MaterialDelHasFiles count@Int64: inklusive #{count} #{pluralDE count "Datei" "Dateien"} MaterialIsVisible: Achtung, dieses Material wurde bereits veröffentlicht. @@ -31,7 +31,7 @@ MaterialArchiveName tid@TermId ssh@SchoolId csh@CourseShorthand materialName@Mat MaterialVideo materialName@MaterialName !ident-ok: #{materialName} - Video MaterialVideoUnsupported: Ihr Browser scheint keine eingebetten Videos zu unterstützen MaterialVideoDownload: Herunterladen -MaterialFree: Kursmaterialien ohne Anmeldung zugänglich +MaterialFree: Kursartmaterialien ohne Anmeldung zugänglich AccessibleSince: Verfügbar seit VisibleFrom: Veröffentlicht FilterMaterialNameSearch !ident-ok: Name diff --git a/messages/uniworx/categories/courses/material/en-eu.msg b/messages/uniworx/categories/courses/material/en-eu.msg index d36393322..b0f2039dd 100644 --- a/messages/uniworx/categories/courses/material/en-eu.msg +++ b/messages/uniworx/categories/courses/material/en-eu.msg @@ -11,27 +11,27 @@ MaterialTypeCode: Code MaterialTypeExample: Example MaterialDescription: Description MaterialVisibleFrom: Visible to participants from -MaterialVisibleFromTip: Never visible to participants if left empty; leaving the date empty is only sensible for unfinished course material or when course material should be provided only to sheet correctors -MaterialVisibleFromEditWarning: This course material has already been published and should not be edited. Doing so might confuse the participants. -MaterialInvisible: This course material is currently invisible to participants! +MaterialVisibleFromTip: Never visible to participants if left empty; leaving the date empty is only sensible for unfinished course type material or when course type material should be provided only to sheet correctors +MaterialVisibleFromEditWarning: This course type material has already been published and should not be edited. Doing so might confuse the participants. +MaterialInvisible: This course type material is currently invisible to participants! MaterialFiles: Files MaterialHeading materialName: #{materialName} -MaterialListHeading: Course materials -MaterialNewHeading: Publish new course material -MaterialNewTitle: New course material -MaterialEditHeading materialName: Edit course material “#{materialName}” -MaterialEditTitle materialName: Edit course material “#{materialName}” -MaterialSaveOk tid ssh csh materialName: Successfully saved “#{materialName}” for course #{tid}-#{ssh}-#{csh} -MaterialNameDup tid ssh csh materialName: Course material with the name “#{materialName}” already exists for course #{tid}-#{ssh}-#{csh} -MaterialDeleteCaption: Do you really want to delete the course material mentioned below? +MaterialListHeading: Course type materials +MaterialNewHeading: Publish new course type material +MaterialNewTitle: New course type material +MaterialEditHeading materialName: Edit course type material “#{materialName}” +MaterialEditTitle materialName: Edit course type material “#{materialName}” +MaterialSaveOk tid ssh csh materialName: Successfully saved “#{materialName}” for course type #{tid}-#{ssh}-#{csh} +MaterialNameDup tid ssh csh materialName: Course type material with the name “#{materialName}” already exists for course type #{tid}-#{ssh}-#{csh} +MaterialDeleteCaption: Do you really want to delete the course type material mentioned below? MaterialDelHasFiles count: including #{count} #{pluralEN count "file" "files"} -MaterialIsVisible: Caution, this course material has already been published. -MaterialDeleted materialName: Successfully deleted course material “#{materialName}” +MaterialIsVisible: Caution, this course type material has already been published. +MaterialDeleted materialName: Successfully deleted course type material “#{materialName}” MaterialArchiveName tid ssh csh materialName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase materialName} MaterialVideo materialName: #{materialName} - Video MaterialVideoUnsupported: Your browser does not seem to support embedded video MaterialVideoDownload: Download -MaterialFree: Course material is publicly available. +MaterialFree: Course type material is publicly available. AccessibleSince: Accessible since VisibleFrom: Published FilterMaterialNameSearch !ident-ok: Name diff --git a/messages/uniworx/categories/courses/participants/de-de-formal.msg b/messages/uniworx/categories/courses/participants/de-de-formal.msg index 8297979c9..3df5414d9 100644 --- a/messages/uniworx/categories/courses/participants/de-de-formal.msg +++ b/messages/uniworx/categories/courses/participants/de-de-formal.msg @@ -2,14 +2,16 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -ParticipantsList: Kursteilnehmerlisten -ParticipantsIntersect: Überschneidung von Kursteilnehmer:innen +ParticipantsList: Kursartteilnehmerlisten +ParticipantsIntersect: Überschneidung von Kursartteilnehmer:innen ParticipantsCsvName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-kursteilnehmer:innen ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName !ident-ok: #{tid} - #{ssh} - #{coursen} -ParticipantsIntersectCourses: Kurse +ParticipantsIntersectCourses: Kursarten CourseParticipantsRegisteredWithoutField n@Int: #{n} #{pluralDE n "Teilnehmeri:in wurde ohne assoziiertes Studienfach" "Teilnehmer:innen wurden ohne assoziierte Studienfächer"} angemeldet, da #{pluralDE n "kein eindeutiges Hauptfach bestimmt werden konnte" "keine eindeutigen Hauptfächer bestimmt werden konnten"} -ParticipantsCsvSheetName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Kursteilnehmer:innen -CourseParticipants n@Int: Derzeit #{n} angemeldete Kursteilnehmer:innen +ParticipantsCsvSheetName tid@TermId ssh@SchoolId: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Kursartteilnehmer:innen +CourseParticipants n@Int: Derzeit #{n} angemeldete Kursartteilnehmer:innen ParticipantsIntersectNotOne: Schnitt AllUsersUnion: Vereinigung aller Teilnehmer:innen -AllUsersIntersection: Schnitt aller Teilneher:innen \ No newline at end of file +AllUsersIntersection: Schnitt aller Teilneher:innen +CourseDeleteActiveParticipants: Diese Kursart hat noch aktive Kursteilnehmer und kann deshalb nicht gelöscht werden. Bitte zuerst alle aktiven Kursteilnehmer entfernen. +CourseDeleteExistExams: Diese Kursart kann nicht gelöscht werden, so lange Prüfungen damit assoziiert werden. \ No newline at end of file diff --git a/messages/uniworx/categories/courses/participants/en-eu.msg b/messages/uniworx/categories/courses/participants/en-eu.msg index 686c0fada..5c98bb4e4 100644 --- a/messages/uniworx/categories/courses/participants/en-eu.msg +++ b/messages/uniworx/categories/courses/participants/en-eu.msg @@ -2,14 +2,16 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -ParticipantsList: Lists of course participants -ParticipantsIntersect: Common course participants +ParticipantsList: Lists of course type participants +ParticipantsIntersect: Common course type participants ParticipantsCsvName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-participants ParticipantsIntersectCourseOption tid@TermId ssh@SchoolId coursen@CourseName: #{tid} - #{ssh} - #{coursen} ParticipantsIntersectCourses: Courses CourseParticipantsRegisteredWithoutField n: #{n} #{pluralEN n "participant was" "participants were"} registered without #{pluralEN n "an associated field of study" "associated fields of study"}, because #{pluralEN n "it" "they"} could not be determined uniquely. ParticipantsCsvSheetName tid ssh: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)} Participants -CourseParticipants n: Currently #{n} course #{pluralEN n "participant" "participants"} +CourseParticipants n: Currently #{n} course type #{pluralEN n "participant" "participants"} ParticipantsIntersectNotOne: Intersection AllUsersUnion: Union of all participants -AllUsersIntersection: Intersection of all participants \ No newline at end of file +AllUsersIntersection: Intersection of all participants +CourseDeleteActiveParticipants: This course type still has active participants. Remove all active participants first if you really want to delete this course. +CourseDeleteExistExams: This course type cannot be deleted, for as long as associated exams exist. \ No newline at end of file diff --git a/messages/uniworx/categories/courses/sheet/de-de-formal.msg b/messages/uniworx/categories/courses/sheet/de-de-formal.msg index 4483a338b..13cb14ec4 100644 --- a/messages/uniworx/categories/courses/sheet/de-de-formal.msg +++ b/messages/uniworx/categories/courses/sheet/de-de-formal.msg @@ -13,8 +13,8 @@ SheetDeleteQuestion: Wollen Sie das unten aufgeführte Übungsblatt und alle zug SheetDeleted: Übungsblatt gelöscht SheetArchiveName tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName !ident-ok: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn} SheetTypeArchiveName tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName renderedSft@Text !ident-ok: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-#{foldCase renderedSft} -SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} wurde gespeichert in Kurs #{tid}-#{ssh}-#{csh} -SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in diesem Kurs #{tid}-#{ssh}-#{csh} +SheetEditOk tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Übungsblatt #{sheetName} wurde gespeichert in Kursart #{tid}-#{ssh}-#{csh} +SheetNameDup tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: Es gibt bereits ein Übungsblatt #{sheetName} in dieser Kursart #{tid}-#{ssh}-#{csh} SheetVisibleFrom: Sichtbar für Teilnehmer:innen ab SheetVisibleFromTip: Ohne Datum nie sichtbar und keine Abgabe möglich; nur für unfertige Blätter leer lassen, deren Bewertung/Fristen sich noch ändern können SheetActiveFrom: Aktiv ab/Beginn Abgabezeitraum @@ -24,7 +24,7 @@ SheetSolutionFromTip: Ohne Datum nie für Teilnehmer:innen sichtbar, Korrektor:i SheetName !ident-ok: Name SheetDescription: Hinweise für Teilnehmer:innen SheetRequireExam: Anmeldung zu einer Prüfung voraussetzen? -SheetRequireExamTip: Wenn die Anmeldung zu einer Prüfung vorausgesetzt wird, können nur Kursteilnehmer:innen abgeben, die zum Zeitpunkt der Abgabe auch zur gewählten Prüfung angemeldet sind. Auch der Download von Übungsblatt-Dateien wird nur zur Prüfung angemeldeten Kursteilnehmer:innen erlaubt. +SheetRequireExamTip: Wenn die Anmeldung zu einer Prüfung vorausgesetzt wird, können nur Kursartteilnehmer:innen abgeben, die zum Zeitpunkt der Abgabe auch zur gewählten Prüfung angemeldet sind. Auch der Download von Übungsblatt-Dateien wird nur zur Prüfung angemeldeten Kursartteilnehmer:innen erlaubt. SheetRequiredExam: Prüfung SheetFormType: Wertung & Abgabe SheetFormTimes: Zeiten @@ -37,13 +37,13 @@ SheetMarkingFiles: Korrektur SheetMarkingTip: Hinweise zur Korrektur, sichtbar nur für Korrektor:innen SheetPersonalisedFilesDownload: Personalisierte Dateien herunterladen SheetPersonalisedFiles: Personalisierte Dateien -SheetPersonalisedFilesTip: Sollen zusätzlich zu den oben angegebenen Dateien noch pro Kursteilnehmer:in personalisierte Dateien hinterlegt werden? Nur die jeweiligen Kursteilnehmer können ihre jeweiligen personalisierten Dateien einsehen. +SheetPersonalisedFilesTip: Sollen zusätzlich zu den oben angegebenen Dateien noch pro Kursartteilnehmer:in personalisierte Dateien hinterlegt werden? Nur die jeweiligen Kursartteilnehmer können ihre jeweiligen personalisierten Dateien einsehen. SheetPersonalisedFilesUpload: Personalisierte Dateien -SheetPersonalisedFilesUploadTip: Laden Sie das Vorlage-Archiv herunter, sortieren Sie darin die personalisierten Dateien in die jeweiligen Verzeichnisse der Kursteilnehmer:innen ein und laden sie das Archiv dann hier wieder hoch. Wenn es eine personalisierte und eine nicht-personalisierte Datei mit dem gleichen Namen gibt, so ersetzt die personalisierte Datei aus Sicht des jeweiligen Teilnehmers/der jeweiligen Teilnehmerin die nicht-personalisierte Datei. +SheetPersonalisedFilesUploadTip: Laden Sie das Vorlage-Archiv herunter, sortieren Sie darin die personalisierten Dateien in die jeweiligen Verzeichnisse der Kursartteilnehmer:innen ein und laden sie das Archiv dann hier wieder hoch. Wenn es eine personalisierte und eine nicht-personalisierte Datei mit dem gleichen Namen gibt, so ersetzt die personalisierte Datei aus Sicht des jeweiligen Teilnehmers/der jeweiligen Teilnehmerin die nicht-personalisierte Datei. SheetPersonalisedFilesKeepExisting: Bestehende Dateien behalten SheetPersonalisedFilesKeepExistingTip: Sollen die hier neu hochgeladenen zu den bestehenden personalisierten Dateien (sofern vorhanden) hinzugefügt werden? Ansonsten ersetzt das neu hochgeladene Archiv vollständig die bestehenden Dateien. SheetPersonalisedFilesAllowNonPersonalisedSubmission: Nicht-personalisierte Abgabe erlauben -SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Sollen auch Kursteilnehmer:innen abgeben dürfen, für die keine personalisierten Dateien hinterlegt wurden? +SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Sollen auch Kursartteilnehmer:innen abgeben dürfen, für die keine personalisierten Dateien hinterlegt wurden? SheetPersonalisedFilesDownloadTemplateHere: Sie können hier ein Vorlage-Archiv für die vom System erwartete Verzeichnisstruktur für personalisierte Übungsblatt-Dateien herunterladen: SheetPersonalisedFilesUsersList: Liste von Teilnehmern mit personalisierten Übungsblatt-Dateien SheetPersonalisedFilesMetaYAMLSeedComment: Dieser String wird in einem kryptographischen Verfahren aus Daten generiert, die Benutzer:in und Übungsblatt eindeutig identifizieren. Er ist geeignet als Seed für einen Pseudozufallsgenerator verwendet zu werden um personalisierte Dateien (teil-)zufällig zu erzeugen. @@ -63,12 +63,12 @@ SheetErrDeadlineEarly: "Aktiv bis/Ende Abgabezeitraum" muss nach "Aktiv ab/Begin SheetErrHintEarly: Hinweise dürfen erst nach Beginn des Abgabezeitraums herausgegeben werden SheetErrSolutionEarly: Lösungen dürfen erst nach Ende der Abgabezeitraums herausgegeben werden SheetErrVisibleWithoutActive: Wird "Sichtbar für Teilnehmer:in ab" angegeben, muss auch "Aktiv ab/Beginn Abgabezeitraum" angegeben werden -SheetSubmissionModeNoneWithoutNotGraded: Es wurde "Keine Abgabe" eingestellt, jedoch nicht "Keine Bewertung". Kursteilnehmer:innen werden nicht abgeben können. +SheetSubmissionModeNoneWithoutNotGraded: Es wurde "Keine Abgabe" eingestellt, jedoch nicht "Keine Bewertung". Kursartteilnehmer:innen werden nicht abgeben können. SheetWarnNoActiveTo: "Aktiv bis/Ende Abgabezeitraum" sollte stets angegeben werden -CountTutProp: Tutorien zählen gegen Proportion -CountTutPropTip: Wenn Abgaben nach Tutorium zugeteilt werden, zählen diese Zuteilungen in Bezug auf den jeweiligen Anteil? +CountTutProp: Kurse zählen gegen Proportion +CountTutPropTip: Wenn Abgaben nach Kurs zugeteilt werden, zählen diese Zuteilungen in Bezug auf den jeweiligen Anteil? ConsiderDeficits: Defizite ausgleichen -ConsiderDeficitsTip: Wenn einem Korrektor/einer Korrektorin (nach aktuellem Datenstand) über alle Blätter des Kurses hinweg weniger Korrekturen zugeteilt wurden als nach den Anteilen vorgesehen, soll versucht werden diese Defizite mit diesem Übungsblatt auszugleichen? +ConsiderDeficitsTip: Wenn einem Korrektor/einer Korrektorin (nach aktuellem Datenstand) über alle Blätter der Kursart hinweg weniger Korrekturen zugeteilt wurden als nach den Anteilen vorgesehen, soll versucht werden diese Defizite mit diesem Übungsblatt auszugleichen? SheetCorrector: Korrektor CorrectorExists: Nutzer:in ist bereits als Korrektor:in eingetragen SheetCorrectorState: Status @@ -82,19 +82,19 @@ RatingPercent: Erreicht IsRated: Korrigiert SheetTypeIsExam: Anrechnung „als Prüfungsaufgabe“ SheetGradingSummaryTitle intgr@Integer: #{intgr} #{pluralDE intgr "Blatt" "Blätter"} -PersonalisedSheetFilesIgnored count@Int64: Es #{pluralDE count "wurde" "wurden"} #{count} hochgeladene #{pluralDE count "Datei" "Dateien"} ignoriert, da sie keinem Übungsblattdatei-Typ oder keinem Kursteilnehmer/keiner Kursteilnehmerin zugeordnet werden #{pluralDE count "konnte" "konnten"}. +PersonalisedSheetFilesIgnored count@Int64: Es #{pluralDE count "wurde" "wurden"} #{count} hochgeladene #{pluralDE count "Datei" "Dateien"} ignoriert, da sie keinem Übungsblattdatei-Typ oder keinem Kursartteilnehmer/keiner Kursartteilnehmerin zugeordnet werden #{pluralDE count "konnte" "konnten"}. PersonalisedSheetFilesIgnoredIntro: Es wurden die folgenden Dateien ignoriert: PersonalisedSheetFilesDownloadRestrictByExamNone: Keine Einschränkung PersonalisedSheetFilesDownloadRestrictByExam: Nur Prüfungsteilnehmer:innen -PersonalisedSheetFilesDownloadRestrictByExamTip: Sollen nur personalisierte Übungsblatt-Dateien exportiert werden, für jene Kursteilnehmer:innen, die auch Teilnehmer:innen einer bestimmten Prüfung sind? +PersonalisedSheetFilesDownloadRestrictByExamTip: Sollen nur personalisierte Übungsblatt-Dateien exportiert werden, für jene Kursartteilnehmer:innen, die auch Teilnehmer:innen einer bestimmten Prüfung sind? PersonalisedSheetFilesDownloadAnonymousField: Anonymisierung -PersonalisedSheetFilesDownloadAnonymousFieldTip: Sollen Verzeichnisnamen innerhalb des Archivs von personalisierten Dateien anonymisiert werden (sie enthalten dann keinerlei unmittelbar identifizierende Informationen zu den Kursteilnehmer:innen), oder sollen die Verzeichnisnamen mit einem Merkmal versehen werden und die Metainformations-Dateien zusätzlich persönliche Daten enthalten? +PersonalisedSheetFilesDownloadAnonymousFieldTip: Sollen Verzeichnisnamen innerhalb des Archivs von personalisierten Dateien anonymisiert werden (sie enthalten dann keinerlei unmittelbar identifizierende Informationen zu den Kursartteilnehmer:innen), oder sollen die Verzeichnisnamen mit einem Merkmal versehen werden und die Metainformations-Dateien zusätzlich persönliche Daten enthalten? PersonalisedSheetFilesMetaFilename uid@CryptoFileNameUser: meta-informationen_#{toPathPiece uid}.yaml PersonalisedSheetFilesArchiveName tid@TermId ssh@SchoolId csh@CourseShorthand shn@SheetName: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-personalisierte_dateien SheetGeneratePseudonym: Generieren SheetFileTypeHeader: Zugehörigkeit SheetCorrectorSubmissionsTip: Abgabe erfolgt über ein Uni2work-externes Verfahren (zumeist in Papierform durch Einwurf) unter Angabe eines persönlichen Pseudonyms. Korrektor:innen können mithilfe des Pseudonyms später Korrekturergebnisse in Uni2work eintragen, damit Sie sie einsehen können. -CorByTut: Zuteilung nach Tutorium +CorByTut: Zuteilung nach Kurs RatingAchievedOf achieved@Points possible@Points: #{achieved} von #{possible} RatingPassed: Bestanden RatingNotPassed: Nicht bestanden @@ -159,9 +159,9 @@ SheetGradingPassAlways: Automatisch bestanden, sobald korrigiert SheetAuthorshipStatementSection: Eigenständigkeitserklärung SheetAuthorshipStatementRequired: Eigenständigkeitserklärung für Übungsblattabgaben einfordern? SheetAuthorshipStatementRequiredTip: Sollen die Abgebenden (bei Abgabegruppen jedes Gruppenmitglied) aufgefordert werden, eine Eigenständigkeitserklärung abzugeben? -SheetAuthorshipStatementRequiredForcedTip: Für dieses Institut sind Eigenständigkeitserklärungen für nicht-prüfungszugehörige Übungsblätter vorgeschrieben. +SheetAuthorshipStatementRequiredForcedTip: Für diesen Bereich sind Eigenständigkeitserklärungen für nicht-prüfungszugehörige Übungsblätter vorgeschrieben. SheetAuthorshipStatementContent: Eigenständigkeitserklärung -SheetAuthorshipStatementContentForcedTip: Für dieses Institut ist die institutsweit vorgegebene Eigenständigkeitserklärung für nicht-prüfungszugehörige Übungsblätter zu verwenden. Benutzerdefinierte Erklärungen sind nicht gestattet. +SheetAuthorshipStatementContentForcedTip: Für diesen Bereich ist die bereichsweit vorgegebene Eigenständigkeitserklärung für nicht-prüfungszugehörige Übungsblätter zu verwenden. Benutzerdefinierte Erklärungen sind nicht gestattet. SheetAuthorshipStatementContentOverridesExamTip: Gehört dieses Übungsblatt zu einer Prüfung mit einer prüfungsweit eingestellten Eigenständigkeitserklärung, so können Sie hier eine für dieses Übungsblatt abweichende Eigenständigkeitserklärung angeben. SheetAuthorshipStatementExamNone: Keine Prüfung SheetAuthorshipStatementExam: Zugeordnete Prüfung diff --git a/messages/uniworx/categories/courses/sheet/en-eu.msg b/messages/uniworx/categories/courses/sheet/en-eu.msg index 51bbf0d3b..a71932447 100644 --- a/messages/uniworx/categories/courses/sheet/en-eu.msg +++ b/messages/uniworx/categories/courses/sheet/en-eu.msg @@ -13,8 +13,8 @@ SheetDeleteQuestion: Do you really want to delete the below-mentioned exercise s SheetDeleted: Successfully deleted exercise sheet SheetArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn} SheetTypeArchiveName tid ssh csh shn renderedSft: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-#{foldCase renderedSft} -SheetEditOk tid ssh csh sheetName: Successfully saved exercise sheet #{sheetName} in course #{tid}-#{ssh}-#{csh} -SheetNameDup tid ssh csh sheetName: There already is an exercise sheet #{sheetName} in course #{tid}-#{ssh}-#{csh} +SheetEditOk tid ssh csh sheetName: Successfully saved exercise sheet #{sheetName} in course type #{tid}-#{ssh}-#{csh} +SheetNameDup tid ssh csh sheetName: There already is an exercise sheet #{sheetName} in course type #{tid}-#{ssh}-#{csh} SheetVisibleFrom: Visible from (for participants) SheetVisibleFromTip: Always invisible for participants and no submission possible if left empty; only leave this field empty for temporary/unfinished sheets SheetActiveFrom: Active from/Submission period start @@ -24,7 +24,7 @@ SheetSolutionFromTip: Always invisible for participants if left empty; corrector SheetName: Name SheetDescription: Description SheetRequireExam: Require registration for an exam? -SheetRequireExamTip: If registration for an exam is required, only course participants that are registered for that exam at the time of submission will be allowed to create submission. Download of sheet files will also be restricted to course participants registered for the exam. +SheetRequireExamTip: If registration for an exam is required, only course type participants that are registered for that exam at the time of submission will be allowed to create submission. Download of sheet files will also be restricted to course type participants registered for the exam. SheetRequiredExam: Exam SheetFormType: Valuation & submission SheetFormTimes: Times @@ -37,15 +37,15 @@ SheetMarkingFiles: Correction SheetMarkingTip: Instructions for correction, visible only to correctors SheetPersonalisedFilesDownload: Download personalised sheet files SheetPersonalisedFiles: Personalised sheet files -SheetPersonalisedFilesTip: Should course participants be assigned personalised sheet files in addition to the files configured above? Only the user to which a file has been assigned may view it. +SheetPersonalisedFilesTip: Should course type participants be assigned personalised sheet files in addition to the files configured above? Only the user to which a file has been assigned may view it. SheetPersonalisedFilesUpload: Personalised sheet files SheetPersonalisedFilesUploadTip: Download the template for a ZIP-archive of personalised sheet files, move files into the directories corresponding to the desired users and upload the archive again. If the name of a personalised file matches the name of an unpersonalised file, the personalised file replaces the unpersonalised one from the respective participants' point of view. SheetPersonalisedFilesKeepExisting: Keep existing files SheetPersonalisedFilesKeepExistingTip: Should the personalised files you upload be added to the already existing ones, if applicable? Otherwise the files you upload will completely replace any existing files. SheetPersonalisedFilesAllowNonPersonalisedSubmission: Allow non-personalised submission -SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Should course participants with no assigned personalised files be allowed to submit anyway? +SheetPersonalisedFilesAllowNonPersonalisedSubmissionTip: Should course type participants with no assigned personalised files be allowed to submit anyway? SheetPersonalisedFilesDownloadTemplateHere: You can download a template for a ZIP-archive of personalised sheet files with the structure that Uni2work expects here: -SheetPersonalisedFilesUsersList: List of course participants who have personalised sheet files +SheetPersonalisedFilesUsersList: List of course type participants who have personalised sheet files SheetPersonalisedFilesMetaYAMLSeedComment: This string was generated cryptographically from data uniquely identifying the user and exercise sheet. You can use it as a seed for a pseudorandom generator for generating (parts of) the personalised files. SheetPersonalisedFilesMetaYAMLNoSeedComment: There is not enough information available to generate a seed. You will have to create the exercise sheet in Uni2work first. Once seeds can be generated they will be generated cryptographically and you may use them to generate (parts of) the personalised files. SheetActiveFromTip: The exercise sheet's assignment will only be available for download and submission starting at this time. If left empty no submission or download of assignment is ever allowed @@ -63,10 +63,10 @@ SheetErrDeadlineEarly: "Submission period end" must be after "Submission period SheetErrHintEarly: "Hint from" must be after "Submission period start" SheetErrSolutionEarly: "Solution from" must be after "Submission period end" SheetErrVisibleWithoutActive: If “Visible from (for participants)” is specified “Active from/Submission period start” must also be specified -SheetSubmissionModeNoneWithoutNotGraded: The sheet was configured to be "No submission" but not "Not marked". Course participants will not be able to submit. +SheetSubmissionModeNoneWithoutNotGraded: The sheet was configured to be "No submission" but not "Not marked". Course type participants will not be able to submit. SheetWarnNoActiveTo: “Active to/Submission period end” should always be specified -CountTutProp: Tutorials count against proportion -CountTutPropTip: If submissions are assigned by tutorial, do those assignments count with regard to the set proportion? +CountTutProp: Courses count against proportion +CountTutPropTip: If submissions are assigned by course, do those assignments count with regard to the set proportion? ConsiderDeficits: Compensate deficits ConsiderDeficitsTip: When a corrector (as per the current state) was assigned fewer or more corrections than would be expected according to their proportions, this is considered a deficit. Should Uni2work try to compensate for these deficits when assigning corrections for this sheet? SheetCorrector: Corrector @@ -82,19 +82,19 @@ RatingPercent: Achieved IsRated: Marked SheetTypeIsExam: Rating „as an exam part“ SheetGradingSummaryTitle intgr: #{intgr} #{pluralEN intgr "sheet" "sheets"} -PersonalisedSheetFilesIgnored count: #{count} uploaded #{pluralEN count "file was" "files were"} ignored because #{pluralEN count "it" "they"} could not be associated with both a sheet file type and a course participant. +PersonalisedSheetFilesIgnored count: #{count} uploaded #{pluralEN count "file was" "files were"} ignored because #{pluralEN count "it" "they"} could not be associated with both a sheet file type and a course type participant. PersonalisedSheetFilesIgnoredIntro: The following files were ignored: PersonalisedSheetFilesDownloadRestrictByExamNone: No restriction PersonalisedSheetFilesDownloadRestrictByExam: Restrict to exam participants PersonalisedSheetFilesDownloadRestrictByExamTip: Only download personalised sheet files for participants also registered to a certain exam? PersonalisedSheetFilesDownloadAnonymousField: Anonymisation -PersonalisedSheetFilesDownloadAnonymousFieldTip: Should the ZIP-archive of personalised files be anonymised (it would then contain no immediately identifiable information regard the course participants) or should directory names be decorated with an identifiable feature of the user and the files of meta information contain additional personal data? +PersonalisedSheetFilesDownloadAnonymousFieldTip: Should the ZIP-archive of personalised files be anonymised (it would then contain no immediately identifiable information regard the course type participants) or should directory names be decorated with an identifiable feature of the user and the files of meta information contain additional personal data? PersonalisedSheetFilesMetaFilename uid: meta-information_#{toPathPiece uid}.yaml PersonalisedSheetFilesArchiveName tid ssh csh shn: #{foldCase (termToText (unTermKey tid))}-#{foldedCase (unSchoolKey ssh)}-#{foldedCase csh}-#{foldedCase shn}-personalised_files SheetGeneratePseudonym: Generate SheetFileTypeHeader: Belongs to SheetCorrectorSubmissionsTip: Submissions are expected to be handed in through some Uni2work-external procedure (usually on paper) marked with your personal pseudonym. Correctors can, using the pseudonym, register the marking in Uni2work for you to review. -CorByTut: Assign by tutorial +CorByTut: Assign by course RatingAchievedOf achieved possible: #{achieved} of #{possible} RatingPassed: Passed RatingNotPassed: Failed diff --git a/messages/uniworx/categories/courses/submission/de-de-formal.msg b/messages/uniworx/categories/courses/submission/de-de-formal.msg index a981a7f75..123cf7bbf 100644 --- a/messages/uniworx/categories/courses/submission/de-de-formal.msg +++ b/messages/uniworx/categories/courses/submission/de-de-formal.msg @@ -49,10 +49,10 @@ SubmissionArchive: Zip-Archiv der Abgabedatei(en) SubmissionArchiveCorrected: Zip-Archiv der Abgabedatei(en) inkl. Korrekturen SubmissionFile: Datei zur Abgabe SubmissionFiles: Abgegebene Dateien -EmailInvitationWarningPrevCoSubmittors: Diese Adresse konnte keinem Kursteilnehmer/keiner Kursteilnehmerin, mit dem Sie schon einmal für diesen Kurs abgegeben haben, zugeordnet werden. Es wird eine Einladung per E-Mail versandt. -EmailInvitationWarningCourseParticipants: Diese Adresse konnte keinem Kursteilnehmer/keiner Kursteilnehmerin zugeordnet werden. Es wird eine Einladung per E-Mail versandt. -MultiUserFieldExplanationPrevCoSubmittors: Dieses Eingabefeld sucht in den Adressen von Kursteilnehmer:innen, für die gesichert werden kann, dass Sie zusammen mit den dahinter stehenden Personen schon einmal für diesen Kurs abgegeben haben. -MultiUserFieldExplanationCourseParticipants: Dieses Eingabefeld sucht in den Adressen von Kursteilnehmer:innen. +EmailInvitationWarningPrevCoSubmittors: Diese Adresse konnte keinem Kursartteilnehmer/keiner Kursartteilnehmerin, mit dem Sie schon einmal für diese Kursart abgegeben haben, zugeordnet werden. Es wird eine Einladung per E-Mail versandt. +EmailInvitationWarningCourseParticipants: Diese Adresse konnte keinem Kursartteilnehmer/keiner Kursartteilnehmerin zugeordnet werden. Es wird eine Einladung per E-Mail versandt. +MultiUserFieldExplanationPrevCoSubmittors: Dieses Eingabefeld sucht in den Adressen von Kursartteilnehmer:innen, für die gesichert werden kann, dass Sie zusammen mit den dahinter stehenden Personen schon einmal für diese Kursart abgegeben haben. +MultiUserFieldExplanationCourseParticipants: Dieses Eingabefeld sucht in den Adressen von Kursartteilnehmer:innen. SubmissionMembers: Abgebende SubmissionMember: Abgebende(r) SubmissionUsersEmpty: Es kann keine Abgabe ohne Abgebende erstellt werden @@ -60,7 +60,7 @@ SubmissionUserAlreadyAdded: Nutzer:in ist bereits als Mitabgebende(r) eingetrage SubmissionWrongSheet: Abgabenummer gehört nicht zum angegebenen Übungsblatt. SubmissionAlreadyExists: Sie haben bereits eine Abgabe zu diesem Übungsblatt. SubmissionAlreadyExistsFor email@UserEmail: #{email} hat bereits eine Abgabe zu diesem Übungsblatt. -NotAParticipant email@UserEmail tid@TermId csh@CourseShorthand: #{email} ist nicht im Kurs #{tid}-#{csh} angemeldet. +NotAParticipant email@UserEmail tid@TermId csh@CourseShorthand: #{email} ist nicht in Kursart #{tid}-#{csh} angemeldet. TooManyParticipants: Es wurden zu viele Mitabgebende angegeben SubmissionCreated: Abgabe erfolgreich angelegt SubmissionUpdated: Abgabe erfolgreich ersetzt @@ -74,7 +74,7 @@ SubmissionUsers: Studenten AssignedTime: Zuteilung SubmissionPseudonym !ident-ok: Pseudonym Pseudonyms: Pseudonyme -CourseCorrectionsTitle: Korrekturen für diesen Kurs +CourseCorrectionsTitle: Korrekturen für diese Kursart SubmissionArchiveName: abgaben SubmissionsAssignUnauthorized num@Int64: #{num} #{pluralDE num "Abgabe" "Abgaben"} können momentan keiner Korrktorin/keinem Korrektor zugeteilt werden (z.B. weil die Abgabe noch offen ist): UpdatedAssignedCorrectorSingle num@Int64: #{num} #{pluralDE num "Abgabe" "Abgaben"} wurden dem neuen Korrektor/der neuen Korrektorin zugeteilt. @@ -155,7 +155,7 @@ SubmissionSomeUsersDuplicateWarning: Manche Abgebende sind auch an einer anderen EMailUnknown email@UserEmail: E-Mail #{email} gehört zu keinem bekannten Benutzer. CorDeficitProportion: Defizit Anteile -CosubmittorTip: Einladungen per E-Mail erhalten genau jene Adressen, für die nicht gesichert werden kann, dass sie mit der dahinter stehenden Person schon einmal für diesen Kurs abgegeben haben. Wenn eine angegebene Adresse einer Person zugeordnet werden kann, mit der Sie in diesem Kurs schon einmal zusammen abgegeben haben, wird der Name der Person angezeigt und die Abgabe erfolgt sofort auch im Namen jener Person. +CosubmittorTip: Einladungen per E-Mail erhalten genau jene Adressen, für die nicht gesichert werden kann, dass sie mit der dahinter stehenden Person schon einmal für diese Kursart abgegeben haben. Wenn eine angegebene Adresse einer Person zugeordnet werden kann, mit der Sie in dieser Kursart schon einmal zusammen abgegeben haben, wird der Name der Person angezeigt und die Abgabe erfolgt sofort auch im Namen jener Person. CorrDownload: Herunterladen SubmissionDownloadAnonymous: Anonymisiert SubmissionDownloadSurnames: Mit Nachnamen @@ -237,9 +237,9 @@ SubmissionFilterAuthorshipStatementCurrent: Aktueller Wortlaut SubmissionNoUsers: Diese Abgabe hat keine assoziierten Benutzer! -CsvColumnCorrectionTerm: Semester des Kurses der Abgabe -CsvColumnCorrectionSchool: Institut des Kurses der Abgabe -CsvColumnCorrectionCourse: Kürzel des Kurses der Abgabe +CsvColumnCorrectionTerm: Jahr der Kursart der Abgabe +CsvColumnCorrectionSchool: Bereich der Kursart der Abgabe +CsvColumnCorrectionCourse: Kürzel der Kursart der Abgabe CsvColumnCorrectionSheet: Name des Übungsblatts der Abgabe CsvColumnCorrectionSubmission: Nummer der Abgabe (uwa…) CsvColumnCorrectionSurname: Nachnamen der Abgebenden als Semikolon (;) separierte Liste diff --git a/messages/uniworx/categories/courses/submission/en-eu.msg b/messages/uniworx/categories/courses/submission/en-eu.msg index 75112ad40..0467e4d20 100644 --- a/messages/uniworx/categories/courses/submission/en-eu.msg +++ b/messages/uniworx/categories/courses/submission/en-eu.msg @@ -49,10 +49,10 @@ SubmissionArchive: Zip-archive of submission files SubmissionArchiveCorrected: Zip-archive of submission files including corrections SubmissionFile: Submission file SubmissionFiles: Submitted files -EmailInvitationWarningPrevCoSubmittors: This address could not be matched to any course participant with whom you have submitted for this course before. An Invitation will be sent via email. -EmailInvitationWarningCourseParticipants: This address coulde not be matched to any course participant. An Invitation will be sent via email. -MultiUserFieldExplanationPrevCoSubmittors: This input searches through the addresses of all course participants for whom it could be determined, that you have already submitted with that person for this course. -MultiUserFieldExplanationCourseParticipants: This input searches through the addresses of all course participants. +EmailInvitationWarningPrevCoSubmittors: This address could not be matched to any course type participant with whom you have submitted for this course type before. An Invitation will be sent via email. +EmailInvitationWarningCourseParticipants: This address coulde not be matched to any course type participant. An Invitation will be sent via email. +MultiUserFieldExplanationPrevCoSubmittors: This input searches through the addresses of all course type participants for whom it could be determined, that you have already submitted with that person for this course. +MultiUserFieldExplanationCourseParticipants: This input searches through the addresses of all course type participants. SubmissionAlreadyExistsFor email: #{email} already has a submission for this sheet. SubmissionUsersEmpty: Submissions may not be created without submittors. SubmissionUserAlreadyAdded: This user is already configured as a submittor @@ -155,7 +155,7 @@ SubmissionSomeUsersDuplicateWarning: Some submittors are also submittors for a d EMailUnknown email: Email #{email} does not belong to any known user. CorDeficitProportion: Deficit (proportion) -CosubmittorTip: Invitations are sent via email to exactly those addresses for which it cannot be determined, that you have already submitted for this course with the associated person, at least once. If one of the specified addresses can be matched to a person with whom you have submitted at least once for this course already, the name of that person will be shown and the submission will immediately be made in their name as well. +CosubmittorTip: Invitations are sent via email to exactly those addresses for which it cannot be determined, that you have already submitted for this course type with the associated person, at least once. If one of the specified addresses can be matched to a person with whom you have submitted at least once for this course type already, the name of that person will be shown and the submission will immediately be made in their name as well. CorrDownload: Download SubmissionDownloadAnonymous: Anonymized SubmissionDownloadSurnames: With surnames @@ -237,9 +237,9 @@ SubmissionFilterAuthorshipStatementCurrent: Current wording SubmissionNoUsers: This submission has no associated users! -CsvColumnCorrectionTerm: Term of the course of the submission -CsvColumnCorrectionSchool: School of the course of the submission -CsvColumnCorrectionCourse: Shorthand of the course of the submission +CsvColumnCorrectionTerm: Term of the course type of the submission +CsvColumnCorrectionSchool: School of the course type of the submission +CsvColumnCorrectionCourse: Shorthand of the course type of the submission CsvColumnCorrectionSheet: Name of the sheet of the submission CsvColumnCorrectionSubmission: Number of the submission (uwa…) CsvColumnCorrectionSurname: Submittor's surnames, separated by semicolon (;) diff --git a/messages/uniworx/categories/courses/tutorial/de-de-formal.msg b/messages/uniworx/categories/courses/tutorial/de-de-formal.msg index eb030ae8c..5a4cef6b6 100644 --- a/messages/uniworx/categories/courses/tutorial/de-de-formal.msg +++ b/messages/uniworx/categories/courses/tutorial/de-de-formal.msg @@ -2,27 +2,27 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -CommTutorialHeading: Tutorium-Mitteilung +CommTutorialHeading: Kursmitteilung ParticipantsN n@Int: #{n} #{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} -TutorialDeleteQuestion: Wollen Sie das unten aufgeführte Tutorium wirklich löschen? -TutorialDeleted: Tutorium gelöscht -TutorialNameTaken tutn@TutorialName: Es existiert bereits anderes Tutorium mit Namen #{tutn} -TutorialCreated tutn@TutorialName: Tutorium #{tutn} erfolgreich angelegt -TutorialEdited tutn@TutorialName: Tutiorium #{tutn} erfolgreich bearbeitet +TutorialDeleteQuestion: Wollen Sie den unten aufgeführten Kurs wirklich löschen? +TutorialDeleted: Kurs gelöscht +TutorialNameTaken tutn@TutorialName: Es existiert bereits ein anderer Kurs mit Namen #{tutn} +TutorialCreated tutn@TutorialName: Kurs #{tutn} erfolgreich angelegt +TutorialEdited tutn@TutorialName: Kurs #{tutn} erfolgreich bearbeitet TutorialEditHeading tutn@TutorialName: #{tutn} bearbeiten TutorEmail: E-Mail -TutorialTutorAlreadyAdded: Ein Tutor/Eine Tutorin mit dieser E-Mail ist bereits für dieses Tutorium eingetragen -TutorialNameTip: Muss innerhalb des Kurses eindeutig sein -TutorialTypePlaceholder: Tutorium, Zentralübung, ... +TutorialTutorAlreadyAdded: Ein Ausblider/Eine Ausbilderin mit dieser E-Mail ist bereits für diesen Kurs eingetragen +TutorialNameTip: Muss innerhalb der Kursart eindeutig sein +TutorialTypePlaceholder: Schulung, Praxisfahrt, ... TutorialTypeTip: Dient nur der Information der Studierenden -TutorialRegGroupTip: Studenten können sich in jeweils maximal einem Tutorium pro Registrierungs-Gruppe anmelden. Ist bei zwei oder mehr Tutorien keine Registrierungs-Gruppe gesetzt zählen diese als in verschiedenen Registrierungs-Gruppen +TutorialRegGroupTip: Studenten können sich in jeweils maximal einem Kurs pro Registrierungs-Gruppe anmelden. Ist bei zwei oder mehr Kurse keine Registrierungs-Gruppe gesetzt zählen diese als in verschiedenen Registrierungs-Gruppen TutorialRegGroup: Registrierungs-Gruppe -TutorialTutorControlled: Tutoren dürfen Tutorium editieren -TutorialTutorControlledTip: Sollen Tutor:innen beliebige Aspekte dieses Tutoriums (Name, Registrierungs-Gruppe, Raum, Zeit, andere Tutor:innen, ...) beliebig editieren dürfen? +TutorialTutorControlled: Ausbilder dürfen Kurs editieren +TutorialTutorControlledTip: Sollen Ausbilder:innen beliebige Aspekte dieses Kurses (Name, Registrierungs-Gruppe, Raum, Zeit, andere Ausbilder:innen, ...) beliebig editieren dürfen? TutorialCapacity: Kapazität TutorialCapacityNonPositive: Kapazität muss größer oder gleich null sein -TutorialCapacityTip: Beschränkt wieviele Studierende sich zu diesem Tutorium anmelden können -TutorialRoomHiddenTip: Soll der Raum nur den Teilnehmer:innen des Tutoriums angezeigt werden? +TutorialCapacityTip: Beschränkt wieviele Studierende sich zu diesem Kurs anmelden können +TutorialRoomHiddenTip: Soll der Raum nur den Teilnehmer:innen des Kurses angezeigt werden? RegisterFrom: Anmeldungen von RegisterTo: Anmeldungen bis TutorialRegisterFromTip: Ohne Datum ist keine eigenständige Anmeldung von Studierenden erlaubt. @@ -33,20 +33,20 @@ TutorialDate: Datum TutorialParticipants: Teilnehmer:innen TutorialEdit: Bearbeiten TutorialDelete: Löschen -TutorialsHeading: Tutorien -TutorialNew: Neues Tutorium -TutorialRegisteredSuccess tutn@TutorialName: Erfolgreich zum Tutorium #{tutn} angemeldet -TutorialDeregisteredSuccess tutn@TutorialName: Erfolgreich vom Tutorium #{tutn} abgemeldet -MailSubjectTutorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand tutn@TutorialName: [#{tid}-#{ssh}-#{csh}] Einladung zum Tutor für #{tutn} -TutorInviteHeading tutn@TutorialName: Einladung zum Tutor/zur Tutorin für #{tutn} -TutorInviteExplanation: Sie wurden eingeladen, Tutor:in zu sein. +TutorialsHeading: Kurse +TutorialNew: Neuer Kurs +TutorialRegisteredSuccess tutn@TutorialName: Erfolgreich zum Kurs #{tutn} angemeldet +TutorialDeregisteredSuccess tutn@TutorialName: Erfolgreich vom Kurs #{tutn} abgemeldet +MailSubjectTutorInvitation tid@TermId ssh@SchoolId csh@CourseShorthand tutn@TutorialName: [#{tid}-#{ssh}-#{csh}] Einladung zum Ausbilder für #{tutn} +TutorInviteHeading tutn@TutorialName: Einladung zum Ausbilder/zur Ausbilderin für #{tutn} +TutorInviteExplanation: Sie wurden eingeladen, Ausbilder:in zu sein. TutorCorrectorInvitationAccepted shn@SheetName: Sie wurden als Korrektor:in für #{shn} eingetragen -TutorialUsersDeregistered count@Int64: #{show count} #{pluralDE count "-Tutorium-Teilnehmer:in" "Tutorium-Teilnehmer:innen" } abgemeldet -TutorialUserDeregister: Vom Tutorium Abmelden +TutorialUsersDeregistered count@Int64: #{show count} #{pluralDE count "-Kursteilnehmer:in" "Kursteilnehmer:innen" } abgemeldet +TutorialUserDeregister: Vom Kurs abmelden TutorialUserSendMail: Mitteilung verschicken TutorialUserPrintQualification: Zertifikat drucken TutorialUserGrantQualification: Qualifikation vergeben TutorialUserRenewQualification: Qualifikation regulär verlängern -TutorialUserRenewedQualification n@Int: Qualifikation für #{tshow n} Tutoriums-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} regulär verlängert -TutorialUserGrantedQualification n@Int: Qualifikation erfolgreich an #{tshow n} Tutoriums-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} vergeben -CommTutorial: Tutorium-Mitteilung \ No newline at end of file +TutorialUserRenewedQualification n@Int: Qualifikation für #{tshow n} Kurs-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} regulär verlängert +TutorialUserGrantedQualification n@Int: Qualifikation erfolgreich an #{tshow n} Kurs-#{pluralDE n "Teilnehmer:in" "Teilnehmer:innen"} vergeben +CommTutorial: Kursmitteilung \ No newline at end of file diff --git a/messages/uniworx/categories/courses/tutorial/en-eu.msg b/messages/uniworx/categories/courses/tutorial/en-eu.msg index d793fe028..20df36d50 100644 --- a/messages/uniworx/categories/courses/tutorial/en-eu.msg +++ b/messages/uniworx/categories/courses/tutorial/en-eu.msg @@ -2,27 +2,27 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -CommTutorialHeading: Tutorial message +CommTutorialHeading: Course message ParticipantsN n: #{n} #{pluralEN n "participant" "participants"} -TutorialDeleteQuestion: Do you really want to delete the tutorial listed below? -TutorialDeleted: Tutorial deleted -TutorialNameTaken tutn: A tutorial named #{tutn} already exists -TutorialCreated tutn: Successfully created tutorial #{tutn} -TutorialEdited tutn: Successfully edited tutorial #{tutn} +TutorialDeleteQuestion: Do you really want to delete the course listed below? +TutorialDeleted: Course deleted +TutorialNameTaken tutn: A course named #{tutn} already exists +TutorialCreated tutn: Successfully created course #{tutn} +TutorialEdited tutn: Successfully edited course #{tutn} TutorialEditHeading tutn: Edit #{tutn} TutorEmail: Email -TutorialTutorAlreadyAdded: An user with this email address is already registered as tutor -TutorialNameTip: Needs to be unique within the course -TutorialTypePlaceholder: Tutorial, Exercise discussion, ... +TutorialTutorAlreadyAdded: An user with this email address is already registered as instructor +TutorialNameTip: Needs to be unique within the course type +TutorialTypePlaceholder: Tutorial, Driving lesson, ... TutorialTypeTip: Only for informational purposes -TutorialRegGroupTip: Course participants may only register for a maximum of one tutorial per registration group. Tutorials that do not have a registration group are treated as being in different registration groups +TutorialRegGroupTip: Course type participants may only register for a maximum of one course per registration group. Courses that do not have a registration group are treated as being in different registration groups TutorialRegGroup: Registration group -TutorialTutorControlled: Tutors may edit tutorial -TutorialTutorControlledTip: Should tutors be allowed to edit arbitrary aspects of this tutorial (name, registration group, room, time, other tutors, ...) at will? +TutorialTutorControlled: Instructors may edit course +TutorialTutorControlledTip: Should instructors be allowed to edit arbitrary aspects of this course (name, registration group, room, time, other instructors, ...) at will? TutorialCapacity: Capacity TutorialCapacityNonPositive: Capacity may not be negative -TutorialCapacityTip: Limits how many course participants may register for this tutorial -TutorialRoomHiddenTip: Should the room only be displayed to tutorial participants? +TutorialCapacityTip: Limits how many course type participants may register for this course +TutorialRoomHiddenTip: Should the room only be displayed to course participants? RegisterFrom: Enrolment starts RegisterTo: Enrolment ends TutorialRegisterFromTip: When left empty students will not be able to enrol themselves @@ -33,21 +33,21 @@ TutorialDate: Date TutorialParticipants: Participants TutorialEdit: Edit TutorialDelete: Delete -TutorialsHeading: Tutorials -TutorialNew: New tutorial -TutorialRegisteredSuccess tutn: Successfully registered for the tutorial #{tutn} -TutorialDeregisteredSuccess tutn: Successfully de-registered for the tutorial #{tutn} -MailSubjectTutorInvitation tid ssh csh tutn: [#{tid}-#{ssh}-#{csh}] Invitation to be a tutor for #{tutn} -TutorInviteHeading tutn: Invitation to be tutor for #{tutn} -TutorInviteExplanation: You were invited to be a tutor. +TutorialsHeading: Courses +TutorialNew: New course +TutorialRegisteredSuccess tutn: Successfully registered for the course #{tutn} +TutorialDeregisteredSuccess tutn: Successfully de-registered for the course #{tutn} +MailSubjectTutorInvitation tid ssh csh tutn: [#{tid}-#{ssh}-#{csh}] Invitation to be a instructor for #{tutn} +TutorInviteHeading tutn: Invitation to be instructor for #{tutn} +TutorInviteExplanation: You were invited to be a instructor. TutorCorrectorInvitationAccepted shn: You are now a corrector for #{shn} -TutorialUsersDeregistered count: Successfully deregistered #{show count} participants from tutorial +TutorialUsersDeregistered count: Successfully deregistered #{show count} participants from course -TutorialUserDeregister: Deregister from tutorial +TutorialUserDeregister: Deregister from course TutorialUserSendMail: Send mail TutorialUserPrintQualification: Print certificate TutorialUserGrantQualification: Grant qualification TutorialUserRenewQualification: Renew qualification -TutorialUserRenewedQualification n@Int: Successfully renewed qualification #{tshow n} tutorial #{pluralEN n "user" "users"} -TutorialUserGrantedQualification n: Successfully granted qualification #{tshow n} tutorial #{pluralEN n "user" "users"} -CommTutorial: Tutorial message +TutorialUserRenewedQualification n@Int: Successfully renewed qualification #{tshow n} course #{pluralEN n "user" "users"} +TutorialUserGrantedQualification n: Successfully granted qualification #{tshow n} course #{pluralEN n "user" "users"} +CommTutorial: Course message diff --git a/messages/uniworx/categories/info/de-de-formal.msg b/messages/uniworx/categories/info/de-de-formal.msg index 1107a2c0d..4ed16f502 100644 --- a/messages/uniworx/categories/info/de-de-formal.msg +++ b/messages/uniworx/categories/info/de-de-formal.msg @@ -7,7 +7,7 @@ InfoSupervisorTitle: Hinweise für Ansprechpartner InfoLecturerTitle: Hinweise für Veranstalter:innen InfoLecturerCourses: Veranstaltungen InfoLecturerExercises: Übungsbetrieb -InfoLecturerTutorials: Tutorien +InfoLecturerTutorials: Kurse InfoLecturerExams: Prüfungen LecturerInfoTooltipNew: Neues Feature LecturerInfoTooltipProblem: Feature mit bekannten Problemen @@ -20,8 +20,8 @@ KnownBugs: Bekannte Bugs ImplementationDetails: Implementierung Clone: Klonen Administrator: Administrator:in -CommCourse: Kursmitteilung +CommCourse: Kursartmitteilung Corrector: Korrektor:in -DefinitionCourseEvents: Kurstermine -DefinitionCourseNews: Kurs-Aktuelles +DefinitionCourseEvents: Kursarttermine +DefinitionCourseNews: Kursart-Aktuelles Invitations: Einladungen diff --git a/messages/uniworx/categories/info/en-eu.msg b/messages/uniworx/categories/info/en-eu.msg index 107df050f..a370481a8 100644 --- a/messages/uniworx/categories/info/en-eu.msg +++ b/messages/uniworx/categories/info/en-eu.msg @@ -3,16 +3,16 @@ # SPDX-License-Identifier: AGPL-3.0-or-later HeadingLegal: Legal -InfoSupervisorTitle: Information for Supervisors -InfoLecturerTitle: Information for lecturers +InfoSupervisorTitle: Information for supervisors +InfoLecturerTitle: Information for course administrators InfoLecturerCourses: Courses -InfoLecturerExercises: Course Exercises -InfoLecturerTutorials: Tutorials +InfoLecturerExercises: Course type exercises +InfoLecturerTutorials: Courses InfoLecturerExams: Exams LecturerInfoTooltipNew: New feature LecturerInfoTooltipProblem: Feature with known issues LecturerInfoTooltipPlanned: Planned feature -LecturerInfoTooltipNewU2W: Unlike UniWorX +LecturerInfoTooltipNewU2W: Unlike FRADrive GlossaryTitle: Glossary FaqTitle: Frequently asked questions VersionHistory: Version history @@ -20,8 +20,8 @@ KnownBugs: Known bugs ImplementationDetails: Implementation Clone: Cloning Administrator: Administrator -CommCourse: Course message +CommCourse: Course type message Corrector: Corrector -DefinitionCourseEvents: Course occurrences -DefinitionCourseNews: Course news +DefinitionCourseEvents: Course type occurrences +DefinitionCourseNews: Course type news Invitations: Invitations diff --git a/messages/uniworx/categories/jobs_handler/de-de-formal.msg b/messages/uniworx/categories/jobs_handler/de-de-formal.msg index 2f14791ac..94fae99d1 100644 --- a/messages/uniworx/categories/jobs_handler/de-de-formal.msg +++ b/messages/uniworx/categories/jobs_handler/de-de-formal.msg @@ -15,7 +15,7 @@ ResetPassword: FRADrive-Passwort ändern bzw. setzen MailSubjectChangeUserDisplayEmail: E-Mail-Adresse in FRADrive verwenden MailIntroChangeUserDisplayEmail displayEmail@UserEmail: Der oben genannte Benutzer/Die oben genannte Benutzerin möchte „#{displayEmail}“ als E-Mail-Adresse in FRADrive verwenden. Wenn Sie diese Aktion nicht selbst ausgelöst haben, ignorieren Sie diese Mitteilung bitte! MailTitleChangeUserDisplayEmail displayName@Text: #{displayName} möchte diese E-Mail-Adresse in FRADrive verwenden -CommCourseSubject: Kursmitteilung +CommCourseSubject: Kursartmitteilung InvitationAcceptDecline: Einladung annehmen/ablehnen InvitationFromTip displayName@Text: Sie erhalten diese Einladung, weil #{displayName} ihren Versand in FRADrive ausgelöst hat. InvitationFromTipAnonymous: Sie erhalten diese Einladung, weil ein nicht eingeloggter Benutzer/eine nichteingeloggte Benutzerin ihren Versand in FRADrive ausgelöst hat. diff --git a/messages/uniworx/categories/jobs_handler/en-eu.msg b/messages/uniworx/categories/jobs_handler/en-eu.msg index 77e0a96f9..3367e7a7a 100644 --- a/messages/uniworx/categories/jobs_handler/en-eu.msg +++ b/messages/uniworx/categories/jobs_handler/en-eu.msg @@ -15,7 +15,7 @@ ResetPassword: Reselt FRADrive password MailSubjectChangeUserDisplayEmail: Set email address in FRADrive MailIntroChangeUserDisplayEmail displayEmail: The user mentioned above wants to set “#{displayEmail}” as their own email address. If you have not caused this email to be sent, please ignore it! MailTitleChangeUserDisplayEmail displayName: #{displayName} wants to set this email address as their own in FRADrive -CommCourseSubject: Course message +CommCourseSubject: Course type message InvitationAcceptDecline: Accept/Decline invitation InvitationFromTip displayName: You are receiving this invitation because #{displayName} has caused it to be sent from within FRADrive. InvitationFromTipAnonymous: You are receiving this invitiation because an user who didn't log in has caused it to be send from within FRADrive. diff --git a/messages/uniworx/categories/print/de-de-formal.msg b/messages/uniworx/categories/print/de-de-formal.msg index 88b38730a..1eb9eb034 100644 --- a/messages/uniworx/categories/print/de-de-formal.msg +++ b/messages/uniworx/categories/print/de-de-formal.msg @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later PJActAcknowledge: Druck und Versand bestätigen +PJActReprint: Erneut drucken über APC PrintJobName: Bezeichnung PrintJobFilename: Dateiname PrintJobId !ident-ok: Id @@ -11,12 +12,13 @@ PrintJobApcAcknowledge: Bestätigungs ID PrintJobAcknowledged: Bestätigt PrintJobUnacknowledged: Noch nicht gedruckt PrintJobAcknowledge n@Int64: #{n} #{pluralDE n "Druckauftrag" "Druckaufräge"} als gedruckt und versendet bestätigt +PrintJobReprint n@Int m@Int: #{n}/#{m} #{pluralDE n "Druckauftrag" "Druckaufräge"} wurden erneut zum Drucken ans APC gesendet; Bestätigungs-Idents wurden dabei nicht verändert und sind nun ggf. doppelt vorhanden. PrintJobAcknowledgeFailed: Keine Druckaufträge bestätigt aufgrund zwischenzeitlicher Änderungen. Bitte die Seite im Browser aktualisieren! PrintJobAcknowledgeQuestion n@Int d@Text: #{n} #{pluralDE n "Druckauftrag" "Druckaufräge"} vom #{d} als gedruckt und versendet bestätigen? PrintJobAcknowledgements: Versanddatum von Briefen an PrintRecipient: Empfänger PrintSender !ident-ok: Sender -PrintCourse: Kurse +PrintCourse: Kursarten PrintQualification: Qualifikation PrintPDF !ident-ok: PDF PrintManualRenewal: Vorfeldführerschein Renewal-Brief testweise versenden diff --git a/messages/uniworx/categories/print/en-eu.msg b/messages/uniworx/categories/print/en-eu.msg index 5cf800eb3..a1090de43 100644 --- a/messages/uniworx/categories/print/en-eu.msg +++ b/messages/uniworx/categories/print/en-eu.msg @@ -3,6 +3,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later PJActAcknowledge: Acknowledge printing and mailing +PJActReprint: Print again via APC PrintJobName: Description PrintJobFilename: Filename PrintJobId: Id @@ -11,12 +12,13 @@ PrintJobApcAcknowledge: Acknowledge ID PrintJobAcknowledged: Acknowledged PrintJobUnacknowledged: Not yet printed PrintJobAcknowledge n: #{n} #{pluralENs n "print-job"} marked as printed and mailed +PrintJobReprint n m: #{n}/#{m} #{pluralENs n "print-job"} were sent for printing to the APC once more. Notice that the acknowledge idents remained unchanged and may thus be duplicated now. PrintJobAcknowledgeFailed: No print-jobs acknowledged, due to intermediate changes. Please reload this page! PrintJobAcknowledgeQuestion n d: Mark #{n} #{pluralENs n "print-job"} issued on #{d} as printed and mailed already? PrintJobAcknowledgements: Sent-dates for Letter to PrintRecipient: Recipient PrintSender: Sender -PrintCourse: Course +PrintCourse: Course type PrintQualification: Qualification PrintPDF: PDF PrintManualRenewal: Manual sending of an apron driver's licence renewal letter diff --git a/messages/uniworx/categories/qualification/de-de-formal.msg b/messages/uniworx/categories/qualification/de-de-formal.msg index 6de4859e5..4f8b887dc 100644 --- a/messages/uniworx/categories/qualification/de-de-formal.msg +++ b/messages/uniworx/categories/qualification/de-de-formal.msg @@ -9,8 +9,12 @@ QualificationValidIndicator: Gültigkeit QualificationValidDuration: Gültigkeitsdauer QualificationAuditDuration: Aufbewahrung Audit Log QualificationRefreshWithin: Erneurerungszeitraum -QualificationRefreshWithinTooltip: Zeitraum für Versand einer Benachrichtigung oder für automatischen Start des E‑Learning +QualificationRefreshWithinTooltip: Optionaler Zeitraum vor Ablauf für automatischen Start des E‑Learnings und Versand einer Benachrichtigung per Brief oder Email +QualificationRefreshReminder: 2. Erinnerung +QualificationRefreshReminderTooltip: Optionaler Zeitraum vor Ablauf zur Versendung einer zweiten Erinnerung per Brief oder Email mit identischen Zugangsdaten, sofern in diesem Zeitraum vor Ablauf noch keine Ablaufbenachrichtigung versendet wurde QualificationElearningStart: Wird das E‑Learning automatisch gestartet? +QualificationExpiryNotification: Ungültigkeitsbenachrichtigung? +QualificationExpiryNotificationTooltip: Nutzer werden benachrichtigt, wenn die Qualifikation ungültig wird, sofern der jeweilige Nutzer in seinen Benutzereinstellungen diese Art Benachrichtigung aktiviert hat. TableQualificationCountActive: Aktive TableQualificationCountActiveTooltip: Anzahl Personen mit momentan gültiger Qualifikation TableQualificationCountTotal: Gesamt @@ -40,7 +44,7 @@ QualificationExpired: Ungültig seit LmsUser: Inhaber LmsURL: Link E‑Learning TableLmsEmail: E‑Mail -TableLmsIdent: E-Learnung Benutzer +TableLmsIdent: E-Learning Benutzer TableLmsElearning: E‑Learning TableLmsPin: E‑Learning Passwort TableLmsResetPin: E-Learning Passwort zurücksetzen? @@ -65,6 +69,7 @@ LmsStatusDelay: Hinweis: Statusänderung können in seltenen Fällen mehrere Stu FilterLmsValid: Aktuell gültig FilterLmsRenewal: Erneuerung anstehend FilterLmsNotified: Benachrichtigt +FilterLmsNotificationDue: Benachrichtigung erforderlich CsvColumnLmsIdent: E‑Learning Identifikator, einzigartig pro Qualifikation und Teilnehmer CsvColumnLmsPin: Passwort E#{nonBreakableDash}Learning Zugang CsvColumnLmsResetPin: Wird das E-Learning Passwort bei der nächsten Synchronisation zurückgesetzt? @@ -102,6 +107,7 @@ QualificationStatusUnblock l@QualificationShorthand n@Int m@Int: #{n}/#{m} #{l} LmsInactive: Aktuell kein E‑Learning aktiv LmsRenewalInstructions: Weitere Anweisungen zur Verlängerung finden Sie im angehängten PDF. Um Missbrauch zu verhindern wurde das PDF mit dem im FRADrive hinterlegten PDF-Passwort des Prüflings verschlüsselt. Falls kein PDF-Passwort manuell hinterlegt wurde, ist das PDF-Passwort die Flughafen Ausweisnummer, inklusive Punkt und der Ziffer danach. LmsNoRenewal: Leider kann diese Qualifikation nicht alleine durch E‑Learning verlängert werden. +LmsRenewalReminder: Erinnerung LmsActNotify: Benachrichtigung E‑Learning erneut per Post oder E-Mail versenden LmsActRenewPin: Neues zufällige E‑Learning Passwort zuweisen LmsActRenewNotify: Neue zufällige E‑Learning Passwort zuweisen und Benachrichtigung per Post oder E-Mail versenden diff --git a/messages/uniworx/categories/qualification/en-eu.msg b/messages/uniworx/categories/qualification/en-eu.msg index 505235e58..659773060 100644 --- a/messages/uniworx/categories/qualification/en-eu.msg +++ b/messages/uniworx/categories/qualification/en-eu.msg @@ -9,8 +9,12 @@ QualificationValidIndicator: Validity QualificationValidDuration: Validity period QualificationAuditDuration: Audit log keept QualificationRefreshWithin: Refresh within -QualificationRefreshWithinTooltip: Period before expiry to send a notification or to start e‑learning +QualificationRefreshWithinTooltip: Optional period before expiry to start e‑learning and send a notification by post or email +QualificationRefreshReminder: 2. Reminder +QualificationRefreshReminderTooltip: Optional period before expiry to send a second notification by post or email once more, provided that no renewal notification was sent in this period before expiry QualificationElearningStart: Is e‑learning automatically started? +QualificationExpiryNotification: Invalidity notification? +QualificationExpiryNotificationTooltip: Qualification holder are notfied upon invalidity, provided they have activated such notification in their user settings. TableQualificationCountActive: Active TableQualificationCountActiveTooltip: Number of currently valid qualification holders TableQualificationCountTotal: Total @@ -38,19 +42,19 @@ QualificationBlockNotify: Send notification QualificationBlockRemoveSupervisor: Remove all supervisors QualificationExpired: Expired on LmsUser: Licensee -LmsURL: Link E-learning +LmsURL: Link E‑learning TableLmsEmail: Email -TableLmsIdent: E-learning user +TableLmsIdent: E‑learning user TableLmsPin: E‑learning password TableLmsElearning: E‑learning -TableLmsResetPin: Reset E-learning password? -TableLmsDatePin: E-learning password created +TableLmsResetPin: Reset E‑learning password? +TableLmsDatePin: E‑learning password created TableLmsDelete: Delete? TableLmsStaff: Staff? TableLmsStarted: Started TableLmsReceived: Last update TableLmsNotified: Notification sent -TableLmsNotifiedTooltip: Notfications are not sent before the LMS acknowledges the opening of the e‑learning course for the user, which may take several hours! +TableLmsNotifiedTooltip: Notfications are not sent before the LMS acknowledges the opening of the e‑learning course type for the user, which may take several hours! TableLmsEnded: Ended TableLmsStatus: Status e‑learning TableLmsStatusTooltip mbMonth: Shows #{maybeToMessage "for up to " (fmap (flip pluralENsN "month") mbMonth) " after closure"} the last e#{nonBreakableDash}learning status change: @@ -65,10 +69,11 @@ LmsStatusDelay: Note that status changes may occassionaly require more than a ho FilterLmsValid: Currently valid FilterLmsRenewal: Renewal due FilterLmsNotified: Notified +FilterLmsNotificationDue: Notification due CsvColumnLmsIdent: E#{nonBreakableDash}learning identifier, unique for each qualification and user CsvColumnLmsPin: Password e#{nonBreakableDash}learning access CsvColumnLmsResetPin: Will the e#{nonBreakableDash}learning password be reset upon next synchronisation? -CsvColumnLmsDelete: Will the identifier be deleted from the E-learning platfrom upon next synchronisation? +CsvColumnLmsDelete: Will the identifier be deleted from the E‑learning platfrom upon next synchronisation? CsvColumnLmsStaff: Is the user an internal staff member? (Legacy, currently ignored) CsvColumnLmsSuccess: Timestamp of successful completion (UTC) CsvColumnLmsFailed: Blockier durch LMS, üblicherweise wegen zu vieler Fehlversuche @@ -79,7 +84,7 @@ LmsResultUpdate: Update of LMS result LmsResultCsvExceptionDuplicatedKey: CSV import with ambiguous key LmsUserlistCsvExceptionDuplicatedKey: CSV import with ambiguous key LmsDirectUpload: Direct upload for automated systems -LmsErrorNoRefreshElearning: Error: E-learning will not be started automatically due to refresh-within time period not being set. +LmsErrorNoRefreshElearning: Error: E‑learning will not be started automatically due to refresh-within time period not being set. MailSubjectQualificationRenewal qname: Qualification #{qname} must be renewed shortly MailSubjectQualificationExpiry qname: Qualification #{qname} expires soon MailSubjectQualificationExpired qname: Qualification #{qname} is no longer valid @@ -101,7 +106,8 @@ QualificationStatusBlock l n m: #{n}/#{m} #{l} revoked QualificationStatusUnblock l n m: #{n}/#{m} #{l} reactivated LmsInactive: Currently no active e‑learning LmsRenewalInstructions: Instruction on how to accomplish the renewal are enclosed in the attached PDF. In order to avoid misuse, the PDF is encrypted with the FRADrive PDF-password of the examinee. If no PDF-password had been chosen yet, then the password is the Fraport id card number of the examinee, including the punctuation mark and the digit thereafter. -LmsNoRenewal: Unfortunately, this particular qualification cannot be renewed through E-learning only. +LmsNoRenewal: Unfortunately, this particular qualification cannot be renewed through e‑learning only. +LmsRenewalReminder: Reminder LmsActNotify: Resend e‑learning notification by post or email LmsActRenewPin: Randomly replace e‑learning password LmsActRenewNotify: Randomly replace e‑learning password and re-send notification by post or email @@ -110,11 +116,11 @@ LmsActRestartWarning: The existing e-learning will be erased immediately! For dr LmsActRestartExtend: Ensure validity for the next # days LmsActRestartUnblock: Undo any revocations LmsActRestartFeedback n@Int m@Int: #{n}/#{m} e-learnings were restarted. -LmsStatusNotificationSent: E-learning password has been sent to examinee or supervisor by letter post or by email; e‑learning is currently open -LmsNotificationSend n: E-learning notifications will be sent to #{n} #{pluralENs n "examinee"} by letter post or by email. -LmsPinRenewal n: E-learning password replaced randomly for #{n} #{pluralENs n "examinee"}. +LmsStatusNotificationSent: E‑learning password has been sent to examinee or supervisor by letter post or by email; e‑learning is currently open +LmsNotificationSend n: E‑learning notifications will be sent to #{n} #{pluralENs n "examinee"} by letter post or by email. +LmsPinRenewal n: E‑learning password replaced randomly for #{n} #{pluralENs n "examinee"}. LmsActionFailed n: No action for #{n} #{pluralENs n "person"}, since there was no ongoing examination. -LmsStarted: E-learning open since +LmsStarted: E‑learning open since LmsAutomaticQueuing n@Natural: The following functions are executed daily at #{show n} o'clock. LmsManualQueuing: The following functions should be executed daily. BtnLmsEnqueue: Enqueue users with expiring qualifications for e‑learning and notify them. diff --git a/messages/uniworx/categories/school/de-de-formal.msg b/messages/uniworx/categories/school/de-de-formal.msg index e3706b656..eedea789f 100644 --- a/messages/uniworx/categories/school/de-de-formal.msg +++ b/messages/uniworx/categories/school/de-de-formal.msg @@ -2,30 +2,30 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -HeadingSchoolList: Institute +HeadingSchoolList: Bereiche SchoolShort: Kürzel SchoolName !ident-ok: Name SchoolLdapOrganisations: Assoziierte LDAP-Fragmente -SchoolLdapOrganisationsTip: Beim Login via LDAP werden dem Nutzer/der Nutzerin alle Institute zugeordnet deren assoziierte LDAP-Fragmente im Eintrag des Nutzer/der Nutzerin gefunden werden +SchoolLdapOrganisationsTip: Beim Login via LDAP werden dem Nutzer/der Nutzerin alle Bereiche zugeordnet deren assoziierte LDAP-Fragmente im Eintrag des Nutzer/der Nutzerin gefunden werden SchoolLdapOrganisationMissing: LDAP-Fragment wird benötigt SchoolExamSection: Prüfungen SchoolExamMinimumRegisterBeforeStart: Minimale Tage zwischen Anmeldebeginn und Termin für Prüfungen -SchoolExamMinimumRegisterBeforeStartTip: Wenn angegeben werden Dozierende gezwungen Anmeldezeitraum und Prüfungstermin stets zusammen einzustellen. +SchoolExamMinimumRegisterBeforeStartTip: Wenn angegeben werden Kursverwaltende gezwungen Anmeldezeitraum und Prüfungstermin stets zusammen einzustellen. SchoolExamMinimumRegisterDuration: Minimale Anmeldedauer für Prüfungen -SchoolExamMinimumRegisterDurationTip: Wenn angegeben werden Dozierende daran gehindert Anmeldefristen von weniger als der minimalen Dauer für ihre Prüfungen einzustellen. +SchoolExamMinimumRegisterDurationTip: Wenn angegeben werden Kursverwaltende daran gehindert Anmeldefristen von weniger als der minimalen Dauer für ihre Prüfungen einzustellen. SchoolExamRequireModeForRegistration: Prüfungsmodus erforderlich für Anmeldung -SchoolExamRequireModeForRegistrationTip: Sollen Dozierende gezwungen werden Prüfungsmodus und Anmeldefrist stets zusammen einzustellen? +SchoolExamRequireModeForRegistrationTip: Sollen Kursverwaltende gezwungen werden Prüfungsmodus und Anmeldefrist stets zusammen einzustellen? SchoolExamDiscouragedModes: Prüfungsmodi mit Warnung ExamCloseMode: Prüfungs-Abschluss SchoolUpdated ssh@SchoolId: #{ssh} erfolgreich angepasst -SchoolTitle ssh@SchoolId: Institut „#{ssh}“ -TitleSchoolNew: Neues Institut anlegen +SchoolTitle ssh@SchoolId: Bereich „#{ssh}“ +TitleSchoolNew: Neues Bereich anlegen SchoolCreated ssh@SchoolId: #{ssh} erfolgreich angelegt -SchoolExists ssh@SchoolId: Institut „#{ssh}“ existiert bereits -SchoolLecturer: Dozent:in -SchoolEvaluation: Kursumfragenverwaltung +SchoolExists ssh@SchoolId: Bereich „#{ssh}“ existiert bereits +SchoolLecturer: Kursverwalter:in +SchoolEvaluation: Kursartumfragenverwaltung SchoolExamOffice: Prüfungsverwaltung SchoolAdmin !ident-ok: Admin diff --git a/messages/uniworx/categories/school/en-eu.msg b/messages/uniworx/categories/school/en-eu.msg index 198bb6c4e..32109bfa4 100644 --- a/messages/uniworx/categories/school/en-eu.msg +++ b/messages/uniworx/categories/school/en-eu.msg @@ -26,7 +26,7 @@ SchoolCreated ssh: Successfully created #{ssh} SchoolExists ssh: A department named „#{ssh}“ already exists SchoolAdmin: Admin SchoolLecturer: Lecturer -SchoolEvaluation: Course evaluation +SchoolEvaluation: Course type evaluation SchoolExamOffice: Exam office SchoolAuthorshipStatementSection: Statements of Authorship diff --git a/messages/uniworx/categories/send/send_notifications/de-de-formal.msg b/messages/uniworx/categories/send/send_notifications/de-de-formal.msg index 3e0070c26..b2a350b3e 100644 --- a/messages/uniworx/categories/send/send_notifications/de-de-formal.msg +++ b/messages/uniworx/categories/send/send_notifications/de-de-formal.msg @@ -4,71 +4,71 @@ #correctionsAssigned.hs + templates MailSubjectCorrectionsAssigned csh@CourseShorthand sheetName@SheetName: Ihnen wurden Korrekturen zu #{sheetName} in #{csh} zugeteilt -MailCorrectionsAssignedIntro courseName@Text termDesc@Text sheetName@SheetName n@Int: #{n} #{pluralDE n "Abgabe wurde" "Abgaben wurden"} Ihnen zur Korrektur für #{sheetName} im Kurs #{courseName} (#{termDesc}) zugeteilt. +MailCorrectionsAssignedIntro courseName@Text termDesc@Text sheetName@SheetName n@Int: #{n} #{pluralDE n "Abgabe wurde" "Abgaben wurden"} Ihnen zur Korrektur für #{sheetName} in Kursart #{courseName} (#{termDesc}) zugeteilt. MailCorrectionsTitle: Zugewiesene Korrekturen #correctionsNotDistributed.hs + templates MailSubjectSubmissionsUnassigned csh@CourseShorthand sheetName@SheetName: Abgaben zu #{sheetName} in #{csh} konnten nicht verteilt werden -MailSubmissionsUnassignedIntro n@Int courseName@Text termDesc@Text sheetName@SheetName: #{n} Abgaben zu #{sheetName} im Kurs #{courseName} (#{termDesc}) konnten nicht automatisiert verteilt werden. +MailSubmissionsUnassignedIntro n@Int courseName@Text termDesc@Text sheetName@SheetName: #{n} Abgaben zu #{sheetName} in Kursart #{courseName} (#{termDesc}) konnten nicht automatisiert verteilt werden. #courseRegistered.hs + templates MailSubjectCourseRegistered csh@CourseShorthand: Sie wurden zu #{csh} angemeldet MailSubjectCourseRegisteredOther displayName@Text csh@CourseShorthand: #{displayName} wurde zu #{csh} angemeldet -MailCourseRegisteredIntro courseName@Text termDesc@Text: Sie wurden im Kurs #{courseName} (#{termDesc}) angemeldet. -MailCourseRegisteredIntroOther displayName@Text courseName@Text termDesc@Text: #{displayName} wurde im Kurs #{courseName} (#{termDesc}) angemeldet. +MailCourseRegisteredIntro courseName@Text termDesc@Text: Sie wurden in Kursart #{courseName} (#{termDesc}) angemeldet. +MailCourseRegisteredIntroOther displayName@Text courseName@Text termDesc@Text: #{displayName} wurde in Kursart #{courseName} (#{termDesc}) angemeldet. #ExamActive.hs + templates MailSubjectExamRegistrationActive csh@CourseShorthand examn@ExamName: Anmeldung für #{examn} in #{csh} ist möglich -MailExamRegistrationActiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich nun für #{examn} im Kurs #{courseName} (#{termDesc}) anmelden. +MailExamRegistrationActiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich nun für #{examn} in Kursart #{courseName} (#{termDesc}) anmelden. MailSubjectExamRegistrationSoonInactive csh@CourseShorthand examn@ExamName: Anmeldung für #{examn} in #{csh} ist nur noch kurze Zeit möglich -MailExamRegistrationSoonInactiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich bald nicht mehr für #{examn} im Kurs #{courseName} (#{termDesc}) anmelden. +MailExamRegistrationSoonInactiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich bald nicht mehr für #{examn} in Kursart #{courseName} (#{termDesc}) anmelden. MailSubjectExamDeregistrationSoonInactive csh@CourseShorthand examn@ExamName: Abmeldung für #{examn} in #{csh} ist nur noch kurze Zeit möglich -MailExamDeregistrationSoonInactiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich bald nicht mehr von #{examn} im Kurs #{courseName} (#{termDesc}) abmelden. +MailExamDeregistrationSoonInactiveIntro courseName@Text termDesc@Text examn@ExamName: Sie können sich bald nicht mehr von #{examn} in Kursart #{courseName} (#{termDesc}) abmelden. #examOffice.hs + templates MailSubjectExamOfficeExamResults coursen@CourseName examn@ExamName: Ergebnisse für #{examn} in #{coursen} sind fertiggestellt -MailExamOfficeExamResultsIntro courseName@Text termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat die Prüfungsleistungen für #{examn} im Kurs #{courseName} (#{termDesc}) freigegeben. +MailExamOfficeExamResultsIntro courseName@Text termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat die Prüfungsleistungen für #{examn} in Kursart #{courseName} (#{termDesc}) freigegeben. MailSubjectExamOfficeExamResultsChanged coursen@CourseName examn@ExamName: Ergebnisse für #{examn} in #{coursen} wurden verändert -MailExamOfficeExamResultsChangedIntro courseName@Text termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat Prüfungsleistungen für #{examn} im Kurs #{courseName} (#{termDesc}) verändert. +MailExamOfficeExamResultsChangedIntro courseName@Text termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat Prüfungsleistungen für #{examn} in Kursart #{courseName} (#{termDesc}) verändert. MailSubjectExamOfficeExternalExamResults coursen@CourseName examn@ExamName: Ergebnisse für #{examn} in #{coursen} -MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat Prüfungsleistungen für #{examn} im Kurs #{coursen} (#{termDesc}) erstellt oder angepasst. +MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: Ein Kursverwalter/Eine Kursverwalterin hat Prüfungsleistungen für #{examn} in Kursart #{coursen} (#{termDesc}) erstellt oder angepasst. #examResult.hs + templates MailSubjectExamResult csh@CourseShorthand examn@ExamName: Ergebnisse für #{examn} in #{csh} wurden herausgegeben -MailExamResultIntro courseName@Text termDesc@Text examn@ExamName: Sie können nun Ihr Ergebnis für #{examn} im Kurs #{courseName} (#{termDesc}) einsehen. +MailExamResultIntro courseName@Text termDesc@Text examn@ExamName: Sie können nun Ihr Ergebnis für #{examn} in Kursart #{courseName} (#{termDesc}) einsehen. #sheetActive.hs + templates MailSubjectSheetActive csh@CourseShorthand sheetName@SheetName: #{sheetName} in #{csh} wurde herausgegeben -MailSheetActiveIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun #{sheetName} im Kurs #{courseName} (#{termDesc}) herunterladen. +MailSheetActiveIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun #{sheetName} in Kursart #{courseName} (#{termDesc}) herunterladen. MailSubjectSheetHint csh@CourseShorthand sheetName@SheetName: Hinweise für #{sheetName} in #{csh} wurden herausgegeben -MailSheetHintIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun die Hinweise für #{sheetName} im Kurs #{courseName} (#{termDesc}) herunterladen. +MailSheetHintIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun die Hinweise für #{sheetName} in Kursart #{courseName} (#{termDesc}) herunterladen. MailSubjectSheetSolution csh@CourseShorthand sheetName@SheetName: Lösungen für #{sheetName} in #{csh} wurden herausgegeben -MailSheetSolutionIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun die Lösungen für #{sheetName} im Kurs #{courseName} (#{termDesc}) herunterladen. +MailSheetSolutionIntro courseName@Text termDesc@Text sheetName@SheetName: Sie können nun die Lösungen für #{sheetName} in Kursart #{courseName} (#{termDesc}) herunterladen. #sheetInactive.hs + templates MailSubjectSheetSoonInactive csh@CourseShorthand sheetName@SheetName: #{sheetName} in #{csh} kann nur noch kurze Zeit abgegeben werden -MailSheetSoonInactiveIntro courseName@Text termDesc@Text sheetName@SheetName: Abgabefrist für #{sheetName} im Kurs #{courseName} (#{termDesc}) endet in Kürze. +MailSheetSoonInactiveIntro courseName@Text termDesc@Text sheetName@SheetName: Abgabefrist für #{sheetName} in Kursart #{courseName} (#{termDesc}) endet in Kürze. MailSubjectSheetInactive csh@CourseShorthand sheetName@SheetName: Abgabezeitraum für #{sheetName} in #{csh} abgelaufen -MailSheetInactiveIntro courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefrist für #{sheetName} im Kurs #{courseName} (#{termDesc}) ist beendet. Es gab #{noneOneMoreDE n "Keine Abgaben" "Nur eine Abgabe von " (toMessage n <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer/einer Teilnehmerin" (toMessage num <> " Teilnehmer:innen")}. -MailSheetInactiveIntroNoUserSubmission courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefrist für #{sheetName} im Kurs #{courseName} (#{termDesc}) ist beendet.#{noneOneMoreDE n "" "Es gab bereits eine Abgabe von " (("Es gab bereits " <> toMessage n) <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer/einer Teilnehmerin" (toMessage num <> " Teilnehmer:innen")}. +MailSheetInactiveIntro courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefrist für #{sheetName} in Kursart #{courseName} (#{termDesc}) ist beendet. Es gab #{noneOneMoreDE n "Keine Abgaben" "Nur eine Abgabe von " (toMessage n <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer/einer Teilnehmerin" (toMessage num <> " Teilnehmer:innen")}. +MailSheetInactiveIntroNoUserSubmission courseName@Text termDesc@Text sheetName@SheetName n@Int num@Int64: Die Abgabefrist für #{sheetName} in Kursart #{courseName} (#{termDesc}) ist beendet.#{noneOneMoreDE n "" "Es gab bereits eine Abgabe von " (("Es gab bereits " <> toMessage n) <> " Abgaben von ")}#{noneOneMoreDE num "" "einem Teilnehmer/einer Teilnehmerin" (toMessage num <> " Teilnehmer:innen")}. MailSheetInactivePseudonymsCount n@Int: Die Anzahl von Abgaben betrifft nur jene, die bereits direkt in FRADrive abgegeben haben. Es #{pluralDE n (("wurde " <> tshow n) <> " Pseudonym") (("wurden " <> tshow n) <> " Pseudonyme")} generiert. -MailSheetInactiveParticipantsCount n@Int: Es #{pluralDE n "ist aktuell" "sind aktuell"} #{n} Teilnehmer zum Kurs angemeldet. +MailSheetInactiveParticipantsCount n@Int: Es #{pluralDE n "ist aktuell" "sind aktuell"} #{n} Teilnehmer zur Kursart angemeldet. #submissionEdited.hs +templates -MailSubjectSubmissionEdited csh@CourseShorthand shn@SheetName: Ihre Abgabe für #{shn} im Kurs #{csh} wurde verändert -MailSubmissionEditedIntro coursen@CourseName shn@SheetName termDesc@Text displayName@Text: #{displayName} hat Ihre Abgabe für #{shn} im Kurs #{coursen} (#{termDesc}) verändert. -MailSubjectSubmissionUserCreated csh@CourseShorthand shn@SheetName: Sie wurden als Mitabgebende:r zu einer Abgabe für #{shn} im Kurs #{csh} hinzugefügt -MailSubjectSubmissionUserCreatedOther displayName@Text csh@CourseShorthand shn@SheetName: Es wurde ein Mitabgebender/eine Mitabgebende zu einer Abgabe für #{shn} im Kurs #{csh} hinzugefügt -MailSubmissionUserCreatedIntro coursen@CourseName shn@SheetName termDesc@Text: Sie wurden als Mitabgebende:r zu einer Abgabe für #{shn} im Kurs #{coursen} (#{termDesc}) hinzugefügt. -MailSubmissionUserCreatedOtherIntro displayName@UserDisplayName coursen@CourseName shn@SheetName termDesc@Text: #{displayName} wurde als Mitabgebender zu einer Abgabe für #{shn} im Kurs #{coursen} (#{termDesc}) hinzugefügt. -MailSubjectSubmissionUserDeleted csh@CourseShorthand shn@SheetName: Sie wurden als Mitabgebende:r von Ihrer Abgabe für #{shn} im Kurs #{csh} entfernt -MailSubjectSubmissionUserDeletedOther displayName@Text csh@CourseShorthand shn@SheetName: Es wurde ein Mitabgebender/eine Mitabgebende von einer Abgabe für #{shn} im Kurs #{csh} entfernt -MailSubmissionUserDeletedIntro coursen@CourseName shn@SheetName termDesc@Text: Sie wurden als Mitabgebende:r von Ihrer Abgabe für #{shn} im Kurs #{coursen} (#{termDesc}) entfernt. -MailSubmissionUserDeletedOtherIntro displayName@UserDisplayName coursen@CourseName shn@SheetName termDesc@Text: #{displayName} wurde als Mitabgebende:r von einer Abgabe für #{shn} im Kurs #{coursen} (#{termDesc}) entfernt. +MailSubjectSubmissionEdited csh@CourseShorthand shn@SheetName: Ihre Abgabe für #{shn} in Kursart #{csh} wurde verändert +MailSubmissionEditedIntro coursen@CourseName shn@SheetName termDesc@Text displayName@Text: #{displayName} hat Ihre Abgabe für #{shn} in Kursart #{coursen} (#{termDesc}) verändert. +MailSubjectSubmissionUserCreated csh@CourseShorthand shn@SheetName: Sie wurden als Mitabgebende:r zu einer Abgabe für #{shn} in Kursart #{csh} hinzugefügt +MailSubjectSubmissionUserCreatedOther displayName@Text csh@CourseShorthand shn@SheetName: Es wurde ein Mitabgebender/eine Mitabgebende zu einer Abgabe für #{shn} in Kursart #{csh} hinzugefügt +MailSubmissionUserCreatedIntro coursen@CourseName shn@SheetName termDesc@Text: Sie wurden als Mitabgebende:r zu einer Abgabe für #{shn} in Kursart #{coursen} (#{termDesc}) hinzugefügt. +MailSubmissionUserCreatedOtherIntro displayName@UserDisplayName coursen@CourseName shn@SheetName termDesc@Text: #{displayName} wurde als Mitabgebender zu einer Abgabe für #{shn} in Kursart #{coursen} (#{termDesc}) hinzugefügt. +MailSubjectSubmissionUserDeleted csh@CourseShorthand shn@SheetName: Sie wurden als Mitabgebende:r von Ihrer Abgabe für #{shn} in Kursart #{csh} entfernt +MailSubjectSubmissionUserDeletedOther displayName@Text csh@CourseShorthand shn@SheetName: Es wurde ein Mitabgebender/eine Mitabgebende von einer Abgabe für #{shn} in Kursart #{csh} entfernt +MailSubmissionUserDeletedIntro coursen@CourseName shn@SheetName termDesc@Text: Sie wurden als Mitabgebende:r von Ihrer Abgabe für #{shn} in Kursart #{coursen} (#{termDesc}) entfernt. +MailSubmissionUserDeletedOtherIntro displayName@UserDisplayName coursen@CourseName shn@SheetName termDesc@Text: #{displayName} wurde als Mitabgebende:r von einer Abgabe für #{shn} in Kursart #{coursen} (#{termDesc}) entfernt. #submissionRated.hs + templates MailSubjectSubmissionRated csh@CourseShorthand: Ihre #{csh}-Abgabe wurde korrigiert -MailSubmissionRatedIntro courseName@Text termDesc@Text: Ihre Abgabe im Kurs #{courseName} (#{termDesc}) wurde korrigiert. +MailSubmissionRatedIntro courseName@Text termDesc@Text: Ihre Abgabe in Kursart #{courseName} (#{termDesc}) wurde korrigiert. AchievedOf achieved@Points possible@Points: #{achieved} von #{possible} Passed: Bestanden NotPassed: Nicht bestanden @@ -87,9 +87,9 @@ MailBodyFradrive: ist die Führerscheinverwaltungsapp der Fraport AG. MailSubjectUserRightsUpdate name@Text: Berechtigungen für #{name} aktualisiert MailSubjectUserSystemFunctionsUpdate name@Text: Berechtigungen für #{name} aktualisiert MailUserRightsIntro name@Text email@UserEmail: #{name} <#{email}> hat folgende FRADrive Berechtigungen: -MailNoLecturerRights: Sie haben derzeit keine Dozent:innen-Rechte. -MailLecturerRights n@Int: Als Dozent:in dürfen Sie Veranstaltungen innerhalb #{pluralDE n "Ihres Instituts" "Ihrer Institute"} anlegen. -MailUserSystemFunctionsIntro name@Text email@UserEmail: #{name} <#{email}> hat folgende FRADrive nicht-institutsbezogene Berechtigungen: +MailNoLecturerRights: Sie haben derzeit keine Kursverwalter:innen-Rechte. +MailLecturerRights n@Int: Als Kursverwalter:in dürfen Sie Veranstaltungen innerhalb #{pluralDE n "Ihres Bereichs" "Ihrer Bereiche"} anlegen. +MailUserSystemFunctionsIntro name@Text email@UserEmail: #{name} <#{email}> hat folgende FRADrive nicht-bereichsbezogene Berechtigungen: MailUserSystemFunctionsNoFunctions: Keine #utils.hs + templates diff --git a/messages/uniworx/categories/send/send_notifications/en-eu.msg b/messages/uniworx/categories/send/send_notifications/en-eu.msg index 94a394d64..b06a1c2eb 100644 --- a/messages/uniworx/categories/send/send_notifications/en-eu.msg +++ b/messages/uniworx/categories/send/send_notifications/en-eu.msg @@ -9,17 +9,17 @@ MailCorrectionsTitle: Assigned corrections #correctionsNotDistributed.hs + templates MailSubjectSubmissionsUnassigned csh sheetName: Corrections for #{sheetName} of #{csh} could not be distributed -MailSubmissionsUnassignedIntro n courseName termDesc sheetName: #{n} corrections for #{sheetName} of the course #{courseName} (#{termDesc}) could not be automatically distributed. +MailSubmissionsUnassignedIntro n courseName termDesc sheetName: #{n} corrections for #{sheetName} of the course type #{courseName} (#{termDesc}) could not be automatically distributed. #courseRegistered.hs + templates MailSubjectCourseRegistered csh: You were enrolled for #{csh} MailSubjectCourseRegisteredOther displayName csh: #{displayName} was enrolled for #{csh} -MailCourseRegisteredIntro courseName termDesc: You were enrolled for the course “#{courseName}” (#{termDesc}) -MailCourseRegisteredIntroOther displayName courseName termDesc: #{displayName} was enrolled for the course “#{courseName}” (#{termDesc}). +MailCourseRegisteredIntro courseName termDesc: You were enrolled for the course type “#{courseName}” (#{termDesc}) +MailCourseRegisteredIntroOther displayName courseName termDesc: #{displayName} was enrolled for the course type “#{courseName}” (#{termDesc}). #examActive.hs + templates MailSubjectExamRegistrationActive csh examn: Registration is now allowed for #{examn} of #{csh} -MailExamRegistrationActiveIntro courseName termDesc examn: You may now register for #{examn} of the course #{courseName} (#{termDesc}). +MailExamRegistrationActiveIntro courseName termDesc examn: You may now register for #{examn} of the course type #{courseName} (#{termDesc}). MailSubjectExamRegistrationSoonInactive csh examn: The registration period for #{examn} of #{csh} ends shortly MailExamRegistrationSoonInactiveIntro courseName termDesc examn: Soon you will no longer be allowed to register for #{examn} of #{courseName} (#{termDesc}). MailSubjectExamDeregistrationSoonInactive csh examn: Deregistration for #{examn} in #{csh} ends shortly @@ -27,15 +27,15 @@ MailExamDeregistrationSoonInactiveIntro courseName termDesc examn: Soon you will #examOffice.hs + templates MailSubjectExamOfficeExamResults coursen examn: Results for #{examn} of #{coursen} are now available -MailExamOfficeExamResultsIntro courseName termDesc examn: A course administrator has made the results for #{examn} of the course #{courseName} (#{termDesc}) available. +MailExamOfficeExamResultsIntro courseName termDesc examn: A course administrator has made the results for #{examn} of the course type #{courseName} (#{termDesc}) available. MailSubjectExamOfficeExamResultsChanged coursen examn: Results for #{examn} of #{coursen} were changed -MailExamOfficeExamResultsChangedIntro courseName termDesc examn: A course administrator has changed exam results for #{examn} of the course #{courseName} (#{termDesc}). +MailExamOfficeExamResultsChangedIntro courseName termDesc examn: A course administrator has changed exam results for #{examn} of the course type #{courseName} (#{termDesc}). MailSubjectExamOfficeExternalExamResults coursen@CourseName examn@ExamName: Results for #{examn} in #{coursen} -MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: A course administrator has changed or initially made available the results for #{examn} of the course {coursen} (#{termDesc}). +MailExamOfficeExternalExamResultsIntro coursen@CourseName termDesc@Text examn@ExamName: A course administrator has changed or initially made available the results for #{examn} of the course type {coursen} (#{termDesc}). #examOffice.hs + templates MailSubjectExamResult csh examn: Results for #{examn} in #{csh} are now available -MailExamResultIntro courseName termDesc examn: You may now view your result for #{examn} of the course #{courseName} (#{termDesc}). +MailExamResultIntro courseName termDesc examn: You may now view your result for #{examn} of the course type #{courseName} (#{termDesc}). #sheetActive.hs + templates MailSubjectSheetActive csh sheetName: #{sheetName} in #{csh} was released @@ -47,10 +47,10 @@ MailSheetSolutionIntro courseName termDesc sheetName: You may now download the s #sheetInactive.hs + templates MailSubjectSheetSoonInactive csh sheetName: The submission period for #{sheetName} of #{csh} ends shortly -MailSheetSoonInactiveIntro courseName termDesc sheetName: Soon you will no longer be allowed to submit for #{sheetName} of the course #{courseName} (#{termDesc}). +MailSheetSoonInactiveIntro courseName termDesc sheetName: Soon you will no longer be allowed to submit for #{sheetName} of the course type #{courseName} (#{termDesc}). MailSubjectSheetInactive csh sheetName: The submission period for #{sheetName} of #{csh} has ended -MailSheetInactiveIntro courseName termDesc sheetName n num: The submission period for #{sheetName} of the course #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant" (toMessage num <> " participants")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "There were no submissions" " made one submission" " submissions"}. -MailSheetInactiveIntroNoUserSubmission courseName termDesc sheetName n num: The submission period for #{sheetName} of the course #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant already" (toMessage num <> " participants already")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "" " made one submission" " submissions"}. +MailSheetInactiveIntro courseName termDesc sheetName n num: The submission period for #{sheetName} of the course type #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant" (toMessage num <> " participants")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "There were no submissions" " made one submission" " submissions"}. +MailSheetInactiveIntroNoUserSubmission courseName termDesc sheetName n num: The submission period for #{sheetName} of the course type #{courseName} (#{termDesc}) has ended. #{noneOneMoreEN num "" "One participant already" (toMessage num <> " participants already")}#{noneOneMoreEN n "" "" (" made " <> toMessage num)}#{noneOneMoreEN n "" " made one submission" " submissions"}. MailSheetInactivePseudonymsCount n: The number of submissions above accounts only for the submissions already made directly in FRADrive. #{n} #{pluralEN n "pseudonym was" "pseudonyms were"} generated. MailSheetInactiveParticipantsCount n: There #{pluralEN n "is" "are"} currently #{n} #{pluralEN n "participant" "participants"} registered for the course. @@ -87,8 +87,8 @@ MailBodyFradrive: is the apron driver's licence management app of Fraport AG. MailSubjectUserRightsUpdate name: Permissions for #{name} changed MailSubjectUserSystemFunctionsUpdate name: Permissions for #{name} changed MailUserRightsIntro name email: #{name} <#{email}> now has the following permissions: -MailNoLecturerRights: You don't currently have lecturer permissions for any department. -MailLecturerRights n: As a lecturer you may create new courses within your #{pluralEN n "department" "departments"}. +MailNoLecturerRights: You don't currently have course administrator permissions for any department. +MailLecturerRights n: As a course administrator you may create new courses within your #{pluralEN n "department" "departments"}. MailUserSystemFunctionsIntro name email: #{name} <#{email}> now has the following, not school restricted, permissions: MailUserSystemFunctionsNoFunctions: None diff --git a/messages/uniworx/categories/settings/auth_settings/de-de-formal.msg b/messages/uniworx/categories/settings/auth_settings/de-de-formal.msg index f91e260cf..e558668d3 100644 --- a/messages/uniworx/categories/settings/auth_settings/de-de-formal.msg +++ b/messages/uniworx/categories/settings/auth_settings/de-de-formal.msg @@ -16,32 +16,32 @@ AuthTagSystemExamOffice: Nutzer:in ist mit systemweiter Prüfungsverwaltung beau AuthTagSystemPrinter: Nutzer:in ist mit systemweiten Druck von Briefen beauftragt AuthTagEvaluation: Nutzer:in ist mit Kursumfragenverwaltung beauftragt AuthTagToken: Nutzer:in präsentiert Authorisierungs-Token -AuthTagNoEscalation: Nutzer-Rechte werden nicht auf fremde Institute ausgeweitet +AuthTagNoEscalation: Nutzer-Rechte werden nicht auf fremde Bereiche ausgeweitet AuthTagDeprecated: Seite ist nicht überholt AuthTagDevelopment: Seite ist nicht in Entwicklung -AuthTagLecturer: Nutzer:in ist Dozent:in +AuthTagLecturer: Nutzer:in ist Kursverwalter:in AuthTagCorrector: Nutzer:in ist Korrektor:in AuthTagExamCorrector: Nutzer:in ist Prüfungskorrektor:in -AuthTagTutor: Nutzer:in ist Tutor:in -AuthTagTutorControl: Tutorierende haben Kontrolle über ihre Tutorium +AuthTagTutor: Nutzer:in ist Ausbilder:in +AuthTagTutorControl: Ausbildende haben Kontrolle über ihren Kurs AuthTagTime: Zeitliche Einschränkungen sind erfüllt AuthTagStaffTime: Zeitliche Einschränkungen für Lehrbeteiligte sind erfüllt -AuthTagCourseTime: Zeitliche Einschränkungen für Kurssichtbarkeit sind erfüllt -AuthTagCourseRegistered: Nutzer:in ist Kursteilnehmer:in -AuthTagTutorialRegistered: Nutzer:in ist Tutoriumsteilnehmer:in +AuthTagCourseTime: Zeitliche Einschränkungen für Kursartsichtbarkeit sind erfüllt +AuthTagCourseRegistered: Nutzer:in ist Kursartteilnehmer:in +AuthTagTutorialRegistered: Nutzer:in ist Kursteilnehmer:in AuthTagExamRegistered: Nutzer:in ist Prüfungsteilnehmer:in AuthTagExamResult: Nutzer:in hat Prüfungsergebnisse AuthTagExamOccurrenceRegistered: Nutzer:in ist für Prüfungsraum/-termin angemeldet AuthTagExamOccurrenceRegistration: Anmeldung zur Prüfung erfolgt inkl. Raum/Termin -AuthTagParticipant: Nutzer:in ist mit Kurs assoziiert -AuthTagRegisterGroup: Nutzer:in ist nicht Mitglied eines anderen Tutoriums mit der selben Registrierungs-Gruppe +AuthTagParticipant: Nutzer:in ist mit Kursart assoziiert +AuthTagRegisterGroup: Nutzer:in ist nicht Mitglied eines anderen Kurses mit der selben Registrierungs-Gruppe AuthTagCapacity: Kapazität ist ausreichend AuthTagEmpty: Ressource ist „leer“ -AuthTagMaterials: Kursmaterialien sind freigegeben +AuthTagMaterials: Kursartmaterialien sind freigegeben AuthTagOwner: Nutzer:in ist Besitzer:in AuthTagPersonalisedSheetFiles: Nutzer:in verfügt über personalisierte Übungsblatt-Dateien AuthTagRated: Korrektur ist bewertet -AuthTagUserSubmissions: Abgaben erfolgen durch Kursteilnehmer:innen +AuthTagUserSubmissions: Abgaben erfolgen durch Kursartteilnehmer:innen AuthTagCorrectorSubmissions: Abgaben erfolgen durch Korrektor:innen AuthTagCorrectionAnonymous: Korrektur ist anonymisiert AuthTagSelf: Nutzer:in greift nur auf eigene Daten zu diff --git a/messages/uniworx/categories/settings/auth_settings/en-eu.msg b/messages/uniworx/categories/settings/auth_settings/en-eu.msg index 5a27d7360..562846f1a 100644 --- a/messages/uniworx/categories/settings/auth_settings/en-eu.msg +++ b/messages/uniworx/categories/settings/auth_settings/en-eu.msg @@ -14,34 +14,34 @@ AuthTagAdmin: User is administrator AuthTagExamOffice: User is part of an exam office AuthTagSystemExamOffice: User is charged with system wide exam administration AuthTagSystemPrinter: User is responsible for system wide letter printing -AuthTagEvaluation: User is charged with course evaluation +AuthTagEvaluation: User is charged with course type evaluation AuthTagToken: User is presenting an authorisation-token AuthTagNoEscalation: User permissions are not being expanded to other departments AuthTagDeprecated: Page is not deprecated AuthTagDevelopment: Page is not in development -AuthTagLecturer: User is lecturer +AuthTagLecturer: User is course administrator AuthTagCorrector: User is corrector AuthTagExamCorrector: User is exam corrector -AuthTagTutor: User is tutor -AuthTagTutorControl: Tutors have control over their tutorial +AuthTagTutor: User is instructor +AuthTagTutorControl: Instructors have control over their course AuthTagTime: Time restrictions are fulfilled AuthTagStaffTime: Time restrictions for teaching staff are fulfilled -AuthTagCourseTime: Time restrictions for course visibility are fulfilled +AuthTagCourseTime: Time restrictions for course type visibility are fulfilled AuthTagCourseRegistered: User is enrolled in course -AuthTagTutorialRegistered: User is tutorial participant +AuthTagTutorialRegistered: User is course participant AuthTagExamRegistered: User is exam participant AuthTagExamResult: User has an exam result AuthTagExamOccurrenceRegistered: User is registered for exam occurrence/room AuthTagExamOccurrenceRegistration: Registration for exam is done including occurrence/room AuthTagParticipant: User participates in course -AuthTagRegisterGroup: User is not participant in any tutorial of the same registration group +AuthTagRegisterGroup: User is not participant in any course of the same registration group AuthTagCapacity: Capacity is sufficient AuthTagEmpty: Resource is “empty” -AuthTagMaterials: Course material is publicly accessable +AuthTagMaterials: Course type material is publicly accessable AuthTagOwner: User is owner AuthTagPersonalisedSheetFiles: User has been assigned personalised sheet files AuthTagRated: Submission is marked -AuthTagUserSubmissions: Submissions are made by course participants +AuthTagUserSubmissions: Submissions are made by course type participants AuthTagCorrectorSubmissions: Submissions are registered by correctors AuthTagCorrectionAnonymous: Correction is anonymised AuthTagSelf: User is only accessing their only data diff --git a/messages/uniworx/categories/settings/de-de-formal.msg b/messages/uniworx/categories/settings/de-de-formal.msg index 189f226e5..966a96328 100644 --- a/messages/uniworx/categories/settings/de-de-formal.msg +++ b/messages/uniworx/categories/settings/de-de-formal.msg @@ -19,7 +19,7 @@ FormCosmetics: Oberfläche Theme: Oberflächen Design Favourites: Anzahl gespeicherter Favoriten FavouritesTip: Betrifft nur automatisch angelegte Favoriten („Kürzlich besucht“) -FavouriteSemesters: Maximale Anzahl an Semestern in Seitenleiste +FavouriteSemesters: Maximale Anzahl an Jahren in Seitenleiste DateTimeFormat: Datums- und Uhrzeitformat DateFormat: Datumsformat TimeFormat: Uhrzeitformat @@ -31,7 +31,7 @@ DownloadFilesTip: Wenn gesetzt werden Dateien automatisch als Download behandelt WarningDays: Fristen-Vorschau WarningDaysTip: Wie viele Tage im Voraus sollen Fristen von Prüfungen etc. auf Ihrer Startseite angezeigt werden? ShowSex: Geschlechter anderer Nutzer:innen anzeigen -ShowSexTip: Sollen in Kursteilnehmer:innen-Tabellen u.Ä. die Geschlechter der Nutzer:innen angezeigt werden? +ShowSexTip: Sollen in Kursartteilnehmer:innen-Tabellen u.Ä. die Geschlechter der Nutzer:innen angezeigt werden? PDFPassword: Passwort zur Verschlüsselung von PDF Anhängen an Email Benachrichtigungens PDFPasswordTip: Achtung, dieses Passwort ist für FRADrive Administratoren einsehbar und wird unverschlüsselt gespeichert! @@ -47,15 +47,15 @@ UserPostLastUpdate: Postadresse zuletzt geändert FormNotifications: Benachrichtigungen -UserSchools: Relevante Institute -UserSchoolsTip: Sie erhalten nur institutweite Benachrichtigungen für Institute, die hier ausgewählt sind. +UserSchools: Relevante Bereiche +UserSchoolsTip: Sie erhalten nur bereichsweite Benachrichtigungen für Bereiche, die hier ausgewählt sind. NotificationSettings: Erwünschte Benachrichtigungen NotificationTriggerKindAll: Für alle Benutzer:innen -NotificationTriggerKindCourseParticipant: Für Kursteilnehmer:innen +NotificationTriggerKindCourseParticipant: Für Kursartteilnehmer:innen NotificationTriggerKindExamParticipant: Für Prüfungsteilnehmer:innen NotificationTriggerKindCorrector: Für Korrektor:innen -NotificationTriggerKindLecturer: Für Dozierende +NotificationTriggerKindLecturer: Für Kursverwaltende NotificationTriggerKindCourseLecturer: Für Kursverwalter:innen NotificationTriggerKindAdmin: Für Administrator:innen NotificationTriggerKindExamOffice: Für Prüfungsverwalter:innen @@ -79,11 +79,12 @@ NotificationTriggerExamDeregistrationSoonInactive: Ich kann mich bald nicht mehr NotificationTriggerExamResult: Ich kann ein neues Prüfungsergebnis einsehen NotificationTriggerExamOfficeExamResults: Ich kann neue Prüfungsergebnisse einsehen NotificationTriggerExamOfficeExamResultsChanged: Prüfungsergebnisse wurden verändert -NotificationTriggerCourseRegistered: Ein:e Kursverwalter:in hat mich zu einem Kurs angemeldet +NotificationTriggerCourseRegistered: Ein:e Kursverwalter:in hat mich zu einer Kursart angemeldet NotificationTriggerSubmissionUserCreated: Ich wurde als Mitabgebender zu einer Übungsblatt-Abgabe hinzugefügt NotificationTriggerSubmissionEdited: Eine meiner Übungsblatt-Abgaben wurde verändert NotificationTriggerSubmissionUserDeleted: Ich wurde als Mitabgebender von einer Übungsblatt-Abgabe entfernt -NotificationTriggerQualification: Eine meiner Qualifikationen läuft ab +NotificationTriggerQualificationExpiry: Eine meiner Qualifikationen läuft ab +NotificationTriggerQualificationReminder: Zweite Erinnerung bei Ablauf einer meiner Qualifikationen UserDisplayNameRules: Vorgaben für den angezeigten Namen @@ -91,19 +92,21 @@ BtnResetTokens: Authorisierungs-Tokens invalidieren TokensLastReset: Tokens zuletzt invalidiert ProfileNever: Nie -ProfileLastLdapSynchronisation: Letzte LDAP-Synchronisation ProfileLdapPrimaryKey: LDAP-Primärschlüssel +ProfileLastLdapSynchronisation: Letzte LDAP-Synchronisation +ProfileLastAvsSynchronisation: Letzte AVS-Synchronisation +ProfileLastAvsSynchError: Letzte AVS-Fehlermeldung NotificationSettingsUpdate: Benachrichtigungs-Einstellungen erfolgreich gespeichert NotificationSettingsHeading displayName@Text: Benachrichtigungs-Einstellungen für #{displayName} FavouriteVisited: Kürzlich besucht -FavouriteParticipant: Ihre Kurse +FavouriteParticipant: Ihre Kursarten FavouriteManual: Favoriten -FavouriteCurrent: Aktueller Kurs +FavouriteCurrent: Aktuelle Kursart FavouritesPlaceholder: Anzahl Favoriten FavouritesNotNatural: Anzahl der Favoriten muss eine natürliche Zahl sein! -FavouritesSemestersPlaceholder: Anzahl Semester -FavouritesSemestersNotNatural: Anzahl der Favoriten-Semester muss eine natürliche Zahl sein! +FavouritesSemestersPlaceholder: Anzahl Jahre +FavouritesSemestersNotNatural: Anzahl der Favoriten-Jahre muss eine natürliche Zahl sein! SettingsUpdate: Einstellungen erfolgreich gespeichert TokensResetSuccess: Authorisierungs-Tokens invalidiert ProfileTitle: Benutzereinstellungen diff --git a/messages/uniworx/categories/settings/en-eu.msg b/messages/uniworx/categories/settings/en-eu.msg index 6dbf5dd95..af8288459 100644 --- a/messages/uniworx/categories/settings/en-eu.msg +++ b/messages/uniworx/categories/settings/en-eu.msg @@ -19,7 +19,7 @@ FormCosmetics: Interface Theme: Theme Favourites: Number of saved favourites FavouritesTip: Only relevant for automatically generated favourites (“visited recently”) -FavouriteSemesters: Maximum number of semesters in favourites bar +FavouriteSemesters: Maximum number of years in favourites bar DateTimeFormat: Date and time format DateFormat: Date format TimeFormat: Time format @@ -31,7 +31,7 @@ DownloadFilesTip: When set, files are automatically treated as downloads. Otherw WarningDays: Deadline-preview WarningDaysTip: How many days ahead should deadlines regarding exams etc. be displayed on the homepage? ShowSex: Show sex of other users -ShowSexTip: Should users' sex be displayed in (among others) lists of course participants? +ShowSexTip: Should users' sex be displayed in (among others) lists of course type participants? PDFPassword: Password to lock PDF email attachments PDFPasswordTip: Please note that this password is displayed to FRADrive admins and is saved unencrypted @@ -52,14 +52,14 @@ UserSchoolsTip: You will only receive department-wide notifications for the sele NotificationSettings: Desired notifications NotificationTriggerKindAll: For all users -NotificationTriggerKindCourseParticipant: For course participants +NotificationTriggerKindCourseParticipant: For course type participants NotificationTriggerKindExamParticipant: For exam participants NotificationTriggerKindCorrector: For correctors -NotificationTriggerKindLecturer: For lecturers +NotificationTriggerKindLecturer: For course administrators NotificationTriggerKindCourseLecturer: For course administrators NotificationTriggerKindAdmin: For administrators NotificationTriggerKindExamOffice: For the exam office -NotificationTriggerKindEvaluation: For course evaluations +NotificationTriggerKindEvaluation: For course type evaluations NotificationTriggerKindSubmissionUser: For participants in an exercise sheet submission NotificationTriggerSubmissionRatedGraded: My submission for an exercise sheet was marked (not purely informational) @@ -83,7 +83,8 @@ NotificationTriggerCourseRegistered: A course administrator has enrolled me in a NotificationTriggerSubmissionUserCreated: I was added to an exercise sheet submission NotificationTriggerSubmissionEdited: One of my exercise sheet submissions was changed NotificationTriggerSubmissionUserDeleted: I was removed from one of my exercise sheet submissions -NotificationTriggerQualification: My Qualifications are about to expire +NotificationTriggerQualificationExpiry: My qualifications are about to expire +NotificationTriggerQualificationReminder: Send second reminder if one of my qualifications is about to expire UserDisplayNameRules: Specification for display names @@ -91,8 +92,10 @@ BtnResetTokens: Invalidate tokens TokensLastReset: Tokens last reset ProfileNever: Never -ProfileLastLdapSynchronisation: Last LDAP synchronisation ProfileLdapPrimaryKey: LDAP primary key +ProfileLastLdapSynchronisation: Last LDAP synchronisation +ProfileLastAvsSynchronisation: Last AVS synchronisation +ProfileLastAvsSynchError: Last AVS Error NotificationSettingsUpdate: Successfully updated notification settings NotificationSettingsHeading displayName: Notification settings for #{displayName} @@ -102,8 +105,8 @@ FavouriteManual: Favourites FavouriteCurrent: Current course FavouritesPlaceholder: Number of favourites FavouritesNotNatural: Number of favourites must be a natural number! -FavouritesSemestersPlaceholder: Number of semesters -FavouritesSemestersNotNatural: Maximum number of semesters in favourites bar must be a natural number! +FavouritesSemestersPlaceholder: Number of years +FavouritesSemestersNotNatural: Maximum number of years in favourites bar must be a natural number! SettingsUpdate: Successfully updated settings TokensResetSuccess: Successfully invalidated all authorisation tokens ProfileTitle: Settings diff --git a/messages/uniworx/categories/settings/personal_settings/de-de-formal.msg b/messages/uniworx/categories/settings/personal_settings/de-de-formal.msg index 147d89ded..cc01e920d 100644 --- a/messages/uniworx/categories/settings/personal_settings/de-de-formal.msg +++ b/messages/uniworx/categories/settings/personal_settings/de-de-formal.msg @@ -10,18 +10,18 @@ LastLogin: Letzter Login NeverSet: Nie ProfileCorrector: Korrektor:in -ProfileCourses: Eigene Kurse +ProfileCourses: Eigene Kursarten ProfileCourseParticipations: Kursanmeldungen ProfileCourseExamResults: Prüfungsleistungen -ProfileTutorials: Eigene Tutorien -ProfileTutorialParticipations: Tutorien +ProfileTutorials: Eigene Kurse +ProfileTutorialParticipations: Kurse ProfileSubmissionGroups: Abgabegruppen ProfileSubmissions: Abgaben ProfileRemark: Hinweis ProfileQualifications: Eigene Qualifikationen PersonalInfoExamAchievementsWip: Die Anzeige von Prüfungsergebnissen wird momentan an dieser Stelle leider noch nicht unterstützt. -PersonalInfoOwnTutorialsWip: Die Anzeige von Tutorien, zu denen Sie als Tutor eingetragen sind wird momentan an dieser Stelle leider noch nicht unterstützt. -PersonalInfoTutorialsWip: Die Anzeige von Tutorien, zu denen Sie angemeldet sind wird momentan an dieser Stelle leider noch nicht unterstützt. +PersonalInfoOwnTutorialsWip: Die Anzeige von Kurse, zu denen Sie als Ausbilder eingetragen sind wird momentan an dieser Stelle leider noch nicht unterstützt. +PersonalInfoTutorialsWip: Die Anzeige von Kurse, zu denen Sie angemeldet sind wird momentan an dieser Stelle leider noch nicht unterstützt. ProfileGroupSubmissionDates: Bei Gruppenabgaben wird kein Datum angezeigt, wenn Sie die Gruppenabgabe nie selbst hochgeladen haben. ProfileCorrectorRemark: Die oberhalb angezeigte Tabelle zeigt nur prinzipielle Einteilungen als Korrektor zu einem Übungsblatt. Auch ohne Einteilung können Korrekturen einzeln zugewiesen werden, welche hier dann nicht aufgeführt werden. ProfileCorrections: Auflistung aller zugewiesenen Korrekturen diff --git a/messages/uniworx/categories/settings/personal_settings/en-eu.msg b/messages/uniworx/categories/settings/personal_settings/en-eu.msg index cc3c63c19..b61ac5678 100644 --- a/messages/uniworx/categories/settings/personal_settings/en-eu.msg +++ b/messages/uniworx/categories/settings/personal_settings/en-eu.msg @@ -11,17 +11,17 @@ LastLogin: Last login NeverSet: Never ProfileCorrector: Corrector ProfileCourses: Own courses -ProfileCourseParticipations: Course registrations +ProfileCourseParticipations: Course type registrations ProfileCourseExamResults: Exam achievements -ProfileTutorials: Own tutorials -ProfileTutorialParticipations: Tutorials +ProfileTutorials: Own courses +ProfileTutorialParticipations: Courses ProfileSubmissionGroups: Submission groups ProfileSubmissions: Submissions ProfileRemark: Remarks ProfileQualifications: Owned Qualifications PersonalInfoExamAchievementsWip: The feature to display your exam achievements has not yet been implemented. -PersonalInfoOwnTutorialsWip: The feature to display tutorials you have been assigned to as tutor has not yet been implemented. -PersonalInfoTutorialsWip: The feature to display tutorials you have registered for has not yet been implemented. +PersonalInfoOwnTutorialsWip: The feature to display courses you have been assigned to as instructor has not yet been implemented. +PersonalInfoTutorialsWip: The feature to display courses you have registered for has not yet been implemented. ProfileGroupSubmissionDates: No date is shown for group submissions if you have never uploaded the submission yourself. ProfileCorrectorRemark: The table above only shows registration as a corrector in principle. Even without registration corrections can be assigned individually and are not listed. ProfileCorrections: List of all assigned corrections diff --git a/messages/uniworx/categories/term/de-de-formal.msg b/messages/uniworx/categories/term/de-de-formal.msg index 80555c631..47343fe21 100644 --- a/messages/uniworx/categories/term/de-de-formal.msg +++ b/messages/uniworx/categories/term/de-de-formal.msg @@ -2,20 +2,20 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -TermStartMustMatchName: Jahreszahl im Namenskürzel stimmt nicht mit Semesterbeginn überein. -TermEndMustBeAfterStart: Semester darf nicht enden, bevor es beginnt. +TermStartMustMatchName: Jahreszahl im Namenskürzel stimmt nicht mit Beginn des gewählten Jahres überein. +TermEndMustBeAfterStart: Jahr darf nicht enden, bevor es beginnt. TermLectureEndMustBeAfterStart: Vorlesungszeit muss vor ihrem Ende anfgangen. -TermStartMustBeBeforeLectureStart: Semester muss vor der Vorlesungszeit beginnen. -TermEndMustBeAfterLectureEnd: Vorlesungszeit muss vor dem Semester enden. +TermStartMustBeBeforeLectureStart: Jahr muss vor der Vorlesungszeit beginnen. +TermEndMustBeAfterLectureEnd: Vorlesungszeit muss vor dem Jahr enden. TermShort: Kürzel -TermCourseCount: Kurse +TermCourseCount: Kursarten TermStart: Anfang Kursperiode TermEnd: Ende Kursperiode -LectureStart: Beginn Kurse -TermEdited tid@TermId: Semester #{tid} erfolgreich editiert. -TermNewTitle: Semester editieren/anlegen. +LectureStart: Beginn Kursart +TermEdited tid@TermId: Jahr #{tid} erfolgreich editiert. +TermNewTitle: Jahr editieren/anlegen. InvalidInput: Ungültige Eingabe, bitte korrigieren. -Term !ident-ok: Semester +Term !ident-ok: Jahr TermPlaceholder: JJJJ TermStartDay: Erster Tag TermEndDay: Letzter Tag @@ -27,16 +27,16 @@ TermLectureEnd: Ende Vorlesungen TermLectureStartTooltip: Muss am oder nach dem Beginn liegen TermLectureEndTooltip: Muss am oder vor dem Ende liegen TermActive: Aktiv -TermActiveTooltip: Zeitraum in dem Lehrende Kurse anlegen dürfen; kann auf angegebene Lehrende eingeschränkt werden +TermActiveTooltip: Zeitraum in dem Lehrende Kursarten anlegen dürfen; kann auf angegebene Lehrende eingeschränkt werden TermActiveForPlaceholder: E-Mail (optional) -NumCourses num@Int64: #{num} #{pluralDE num "Kurs" "Kurse"} -TermsHeading: Semesterübersicht -TermEditHeading: Semester editieren/anlegen +NumCourses num@Int64: #{num} #{pluralDE num "Kursart" "Kursarten"} +TermsHeading: Jahresübersicht +TermEditHeading: Jahr editieren/anlegen TermFormHolidaysAlreadyAdded: Alle neuen Feiertage sind bereits eingetragen TermFormHolidaysFrom: Von TermFormHolidaysTo: Bis -TermExists: Semester existiert bereits +TermExists: Jahr existiert bereits TermFormActiveFrom: Von TermFormActiveTo: Bis diff --git a/messages/uniworx/categories/term/en-eu.msg b/messages/uniworx/categories/term/en-eu.msg index 7880cc072..362ab2e98 100644 --- a/messages/uniworx/categories/term/en-eu.msg +++ b/messages/uniworx/categories/term/en-eu.msg @@ -2,20 +2,20 @@ # # SPDX-License-Identifier: AGPL-3.0-or-later -TermStartMustMatchName: Shorthand number does not match semester start. -TermEndMustBeAfterStart: Semester end may not be before semester start. +TermStartMustMatchName: Shorthand number does not match start of year. +TermEndMustBeAfterStart: Year end may not be before start of year. TermLectureEndMustBeAfterStart: Lecture start may not be after lecture end. -TermStartMustBeBeforeLectureStart: Semester start must be before lecture start. -TermEndMustBeAfterLectureEnd: Lecture end must be before semester end. +TermStartMustBeBeforeLectureStart: Year start must be before lecture start. +TermEndMustBeAfterLectureEnd: Lecture end must be before end of year. TermShort: Shorthand TermCourseCount: Courses TermStart: Start of teaching period TermEnd: End of teaching perios LectureStart: Courses start -TermEdited tid: Successfully edited semester #{tid} -TermNewTitle: Edit/create semester +TermEdited tid: Successfully edited year #{tid} +TermNewTitle: Edit/create year InvalidInput: Invalid input -Term: Semester +Term: Year TermPlaceholder: YYYY TermStartDay: Starting day TermEndDay: Last day @@ -27,11 +27,11 @@ TermLectureEnd: Lectures end TermLectureStartTooltip: Must be on or after starting day TermLectureEndTooltip: Must be before or on ending day TermActive: Active -TermActiveTooltip: Timeframe when lecturers may add courses; maybe restricted for specified lecturers +TermActiveTooltip: Timeframe when course administrators may add courses; maybe restricted for specified course administrators TermActiveForPlaceholder: Email (optional) NumCourses num: #{num} #{pluralEN num "course" "courses"} -TermsHeading: Semesters -TermEditHeading: Edit semester +TermsHeading: Years +TermEditHeading: Edit year TermFormHolidaysAlreadyAdded: All new holidays were already entered TermFormHolidaysFrom: From diff --git a/messages/uniworx/categories/user/de-de-formal.msg b/messages/uniworx/categories/user/de-de-formal.msg index 4bc183394..b11ff586a 100644 --- a/messages/uniworx/categories/user/de-de-formal.msg +++ b/messages/uniworx/categories/user/de-de-formal.msg @@ -35,7 +35,7 @@ UserSystemFunctionsNotChanged: Es wurden keine systemweiten Rollen angepasst AuthPWHash pwHash@Text !ident-ok: FRADrive AuthPWHashAlreadyConfigured: Nutzer:in meldet sich bereits mit FRADrive spezifischer Kennung an AuthPWHashConfigured: Nutzer:in meldet sich nun mit FRADrive spezifischer Kennung an -UsersCourseSchool: Institut +UsersCourseSchool: Bereich ActionNoUsersSelected: Keine Benutzer:innen ausgewählt SynchroniseAvsUserQueued n@Int: AVS-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen SynchroniseLdapUserQueued n@Int: LDAP-Synchronisation von #{n} #{pluralDE n "Benutzer:in" "Benutzer:innen"} angestoßen @@ -66,12 +66,12 @@ UserPasswordHeadingFor: Passwort ändern für PasswordChangedSuccess: Passwort erfolgreich geändert MailSubjectSchoolFunctionInvitation school@SchoolName renderedFunction@Text: #{renderedFunction}-Einladung für „#{school}“ MailSchoolFunctionInviteHeading school@SchoolName renderedFunction@Text: #{renderedFunction}-Einladung für „#{school}“ -SchoolFunctionInviteExplanation renderedFunction@Text: Sie wurden eingeladen, als #{renderedFunction} für ein Institut zu wirken. Sie erhalten, nachdem Sie die Einladung annehmen, erweiterte Rechte innerhalb des Instituts. -SchoolFunctionInvitationAccepted school@SchoolName renderedFunction@Text: #{renderedFunction}-Einladung als Dozent:in für „#{school}“ angenommen +SchoolFunctionInviteExplanation renderedFunction@Text: Sie wurden eingeladen, als #{renderedFunction} für einen Bereich zu wirken. Sie erhalten, nachdem Sie die Einladung annehmen, erweiterte Rechte innerhalb des Bereichs. +SchoolFunctionInvitationAccepted school@SchoolName renderedFunction@Text: #{renderedFunction}-Einladung als Kursverwalter:in für „#{school}“ angenommen FunctionaryInviteFunction: Funktion -FunctionaryInviteSchool: Institut +FunctionaryInviteSchool: Bereich FunctionaryInviteField: Einzuladende E-Mail-Adressen -FunctionaryInviteHeading: Institut-Funktionäre hinzufügen +FunctionaryInviteHeading: Bereich-Funktionäre hinzufügen FunctionariesInvited n@Int: #{n} #{pluralDE n "Funktionär:in" "Funktionäre"} per E-Mail eingeladen FunctionariesAdded n@Int: #{n} #{pluralDE n "Funktionär:in" "Funktionäre"} eingetragen AdminUserRightsHeading: Benutzerrechte @@ -82,8 +82,8 @@ UserGroupSubmissionsKept n@Int: #{tshow n} Gruppenabgaben verbleiben in der Date UserSubmissionGroupsDeleted count@Int64: #{tshow count} benannte Abgabengruppen wurden gelöscht, da sie ohne den Nutzer/die Nutzerin leer wären. AuthMode: Authentifizierungsmodus Aborted: Abgebrochen -CourseUserRegister: Zum Kurs anmelden -CourseUserDeregister: Vom Kurs abmelden +CourseUserRegister: Zur Kursart anmelden +CourseUserDeregister: Von Kursart abmelden NewPasswordLinkTip: Das Passwort Ihrer Uni2work-internen Kennung können Sie auf der folgenden Seite setzen: NewPasswordLink: Neues Passwort setzen UserAccountDeleteWarning: Achtung, dies löscht den kompletten Benutzer/die komplette Benutzerin unwiderruflich und mit allen assoziierten Daten aus der Datenbank. Prüfungsdaten müssen jedoch langfristig gespeichert bleiben! diff --git a/messages/uniworx/utils/buttons/de-de-formal.msg b/messages/uniworx/utils/buttons/de-de-formal.msg index adf9d75ab..8252a3a1c 100644 --- a/messages/uniworx/utils/buttons/de-de-formal.msg +++ b/messages/uniworx/utils/buttons/de-de-formal.msg @@ -7,8 +7,9 @@ BtnAbort: Abbrechen BtnDelete: Löschen BtnRegister: Anmelden BtnDeregister: Abmelden -BtnCourseRegister: Zum Kurs anmelden -BtnCourseDeregister: Vom Kurs abmelden +MassRegister: Andere anmelden +BtnCourseRegister: Zur Kursart anmelden +BtnCourseDeregister: Von Kursart abmelden BtnExamRegister: Anmelden zur Prüfung BtnExamRegisterOccurrence: Anmelden zum Prüfungstermin/-raum BtnExamSwitchOccurrence: Zu Prüfungstermin/-raum wechseln diff --git a/messages/uniworx/utils/buttons/en-eu.msg b/messages/uniworx/utils/buttons/en-eu.msg index 5b3a7aadc..a83a7b3aa 100644 --- a/messages/uniworx/utils/buttons/en-eu.msg +++ b/messages/uniworx/utils/buttons/en-eu.msg @@ -7,6 +7,7 @@ BtnAbort: Abort BtnDelete: Delete BtnRegister: Register BtnDeregister: Deregister +MassRegister: Register others BtnCourseRegister: Enrol for course BtnCourseDeregister: Leave course BtnExamRegister: Enrol for exam diff --git a/messages/uniworx/utils/navigation/breadcrumbs/de-de-formal.msg b/messages/uniworx/utils/navigation/breadcrumbs/de-de-formal.msg index 6e49ab72d..3d083e6e7 100644 --- a/messages/uniworx/utils/navigation/breadcrumbs/de-de-formal.msg +++ b/messages/uniworx/utils/navigation/breadcrumbs/de-de-formal.msg @@ -10,29 +10,29 @@ BreadcrumbCourseNotes: Kursnotizen BreadcrumbHiWis: Korrektor:innen BreadcrumbMaterial !ident-ok: Material BreadcrumbSheet: Übungsblatt -BreadcrumbTutorial: Tutorium +BreadcrumbTutorial: Kurs BreadcrumbExam: Prüfung BreadcrumbCourseRegister: Anmelden BreadcrumbCourseFavourite: Favorisieren -BreadcrumbCourse: Kurs -BreadcrumbTerm !ident-ok: Semester -BreadcrumbSchool: Institut +BreadcrumbCourse: Kursart +BreadcrumbTerm !ident-ok: Jahr +BreadcrumbSchool: Bereich BreadcrumbUser: Benutzer:in BreadcrumbStatic: Statische Resource BreadcrumbWellKnown: Benannte statische Resource BreadcrumbMetrics: Metriken BreadcrumbLecturerInvite: Einladung zum Kursverwalter BreadcrumbExamOfficeUserInvite: Einladung bzgl. Prüfungsleistungen -BreadcrumbFunctionaryInvite: Einladung zum Instituts-Funktionär +BreadcrumbFunctionaryInvite: Einladung zum Bereichs-Funktionär BreadcrumbUserDelete: Nutzer-Account löschen BreadcrumbUserHijack: Nutzer-Sitzung übernehmen BreadcrumbSystemMessage: Statusmeldung BreadcrumbSubmission: Abgabe BreadcrumbCourseNews: Kursnachricht BreadcrumbCourseNewsDelete: Kursnachricht löschen -BreadcrumbCourseEventDelete: Kurstermin löschen +BreadcrumbCourseEventDelete: Kursarttermin löschen BreadcrumbProfile: Einstellungen -BreadcrumbCourseParticipantInvitation: Einladung als Kursteilnehmer:in +BreadcrumbCourseParticipantInvitation: Einladung als Kursartteilnehmer:in BreadcrumbMaterialArchive: Archiv BreadcrumbMaterialFile: Datei BreadcrumbMaterialVideo !ident-ok: Video @@ -42,7 +42,7 @@ BreadcrumbSheetPseudonym !ident-ok: Pseudonym BreadcrumbSheetCorrectorInvite: Einladung als Korrektor:in BreadcrumbSheetFile: Datei BreadcrumbTutorialRegister: Anmelden -BreadcrumbTutorInvite: Einladung als Tutor:in +BreadcrumbTutorInvite: Einladung als Ausbilder:in BreadcrumbExamCorrectorInvite: Einladung als Prüfungskorrektor:in BreadcrumbExamParticipantInvite: Einladung als Prüfungsteilnehmer:in BreadcrumbExamRegister: Anmelden @@ -57,8 +57,8 @@ BreadcrumbExternalExamUsers: Teilnehmer:in BreadcrumbExternalExamGrades: Prüfungsleistungen BreadcrumbExternalExamStaffInvite: Einladung als Prüfer:in BreadcrumbExternalExamCorrect: Prüfungsleistungen eintragen -BreadcrumbParticipantsList: Kursteilnehmerlisten -BreadcrumbParticipants: Kursteilnehmerliste +BreadcrumbParticipantsList: Kursartteilnehmerlisten +BreadcrumbParticipants: Kursartteilnehmerliste BreadcrumbExamAutoOccurrence: Automatische Termin-/Raumverteilung BreadcrumbStorageKey: Lokalen Schlüssel generieren BreadcrumbMessageHide: Verstecken @@ -76,8 +76,8 @@ BreadcrumbAdminFeaturesHeading: Studiengänge BreadcrumbAdminTest: Admin-Demo BreadcrumbAdminErrMsg: Fehlermeldung entschlüsseln BreadcrumbAdminTokens: Tokens ausstellen -BreadcrumbSchoolList: Institute -BreadcrumbSchoolNew: Neues Institut anlegen +BreadcrumbSchoolList: Bereiche +BreadcrumbSchoolNew: Neuen Bereich anlegen BreadcrumbExamOfficeExams: Prüfungen BreadcrumbExamOfficeFields: Fächer BreadcrumbExamOfficeUsers: Benutzer:innen @@ -91,30 +91,30 @@ BreadcrumbInstance: Instanz-Identifikation BreadcrumbUserDisplayEmail: E‑Mail-Adresse BreadcrumbProfileData: Persönliche Daten BreadcrumbAuthPreds: Authorisierungseinstellungen -BreadcrumbTermShow: Semester -BreadcrumbTermCreate: Neues Semester anlegen -BreadcrumbTermEdit: Semester editieren -BreadcrumbTermCurrent: Aktuelles Semester -BreadcrumbParticipantsIntersect: Überschneidung von Kursteilnehmer:innen -BreadcrumbCourseList: Kurse -BreadcrumbCourseNew: Neuen Kurs anlegen -BreadcrumbCourseEdit: Kurs editieren -BreadcrumbCourseMembers: Kursteilnehmer:innen -BreadcrumbCourseAddMembers: Kursteilnehmer:innen hinzufügen +BreadcrumbTermShow: Jahr +BreadcrumbTermCreate: Neues Jahr anlegen +BreadcrumbTermEdit: Jahr editieren +BreadcrumbTermCurrent: Aktuelles Jahr +BreadcrumbParticipantsIntersect: Überschneidung von Kursartteilnehmer:innen +BreadcrumbCourseList: Kursarten +BreadcrumbCourseNew: Neue Kursart anlegen +BreadcrumbCourseEdit: Kursart editieren +BreadcrumbCourseMembers: Kursartteilnehmer:innen +BreadcrumbCourseAddMembers: Kursartteilnehmer:innen hinzufügen BreadcrumbCourseExamOffice: Prüfungsbeauftragte BreadcrumbCorrectionsAssign: Zuteilung der Korrekturen BreadcrumbSheetList: Übungsblätter BreadcrumbSheetNew: Neues Übungsblatt anlegen BreadcrumbSheetCurrent: Aktuelles Übungsblatt BreadcrumbSheetOldUnassigned: Abgaben ohne Korrektor:in -BreadcrumbCourseCommunication: Kursmitteilung (E‑Mail) -BreadcrumbTutorialList: Tutorien -BreadcrumbTutorialNew: Neues Tutorium anlegen -BreadcrumbCourseDelete: Kurs löschen -BreadcrumbCourseNewsNew: Neue Kursnachricht -BreadcrumbCourseNewsEdit: Kursnachricht bearbeiten -BreadcrumbCourseEventNew: Neuer Kurstermin -BreadcrumbCourseEventEdit: Kurstermin bearbeiten +BreadcrumbCourseCommunication: Kursartmitteilung (E‑Mail) +BreadcrumbTutorialList: Kurse +BreadcrumbTutorialNew: Neuen Kurs anlegen +BreadcrumbCourseDelete: Kursart löschen +BreadcrumbCourseNewsNew: Neue Kursartnachricht +BreadcrumbCourseNewsEdit: Kursartnachricht bearbeiten +BreadcrumbCourseEventNew: Neuer Kursarttermin +BreadcrumbCourseEventEdit: Kursarttermin bearbeiten BreadcrumbExamList: Prüfungen BreadcrumbExamNew: Neue Prüfung anlegen BreadcrumbExamEdit: Prüfung bearbeiten @@ -122,8 +122,8 @@ BreadcrumbExamUsers: Teilnehmer:innen BreadcrumbExamGrades: Prüfungsleistungen BreadcrumbExamAddMembers: Prüfungsteilnehmer hinzufügen BreadcrumbExamCorrect: Prüfungsergebnisse eintragen -BreadcrumbTutorialDelete: Tutorium löschen -BreadcrumbTutorialEdit: Tutorium editieren +BreadcrumbTutorialDelete: Kurs löschen +BreadcrumbTutorialEdit: Kurs editieren BreadcrumbTutorialComm: Mitteilung an Teilnehmer:innen BreadcrumbSheetEdit: Übungsblatt editieren BreadcrumbSheetDelete: Übungsblatt löschen diff --git a/messages/uniworx/utils/navigation/breadcrumbs/en-eu.msg b/messages/uniworx/utils/navigation/breadcrumbs/en-eu.msg index 705ec1d6c..deadd76e7 100644 --- a/messages/uniworx/utils/navigation/breadcrumbs/en-eu.msg +++ b/messages/uniworx/utils/navigation/breadcrumbs/en-eu.msg @@ -6,16 +6,16 @@ BreadcrumbCsvOptions: csv-options BreadcrumbSubmissionFile: File BreadcrumbSubmissionUserInvite: Invitation to participate in a submission BreadcrumbCryptoIDDispatch: CryptoID-redirect -BreadcrumbCourseNotes: Course notes +BreadcrumbCourseNotes: Course type notes BreadcrumbHiWis: Correctors BreadcrumbMaterial: Material BreadcrumbSheet: Exercise sheet -BreadcrumbTutorial: Tutorial +BreadcrumbTutorial: Course BreadcrumbExam: Exam BreadcrumbCourseRegister: Register BreadcrumbCourseFavourite: Favourite -BreadcrumbCourse: Course -BreadcrumbTerm: Semester +BreadcrumbCourse: Course type +BreadcrumbTerm: Year BreadcrumbSchool: Department BreadcrumbUser: User BreadcrumbStatic: Static resource @@ -28,11 +28,11 @@ BreadcrumbUserDelete: Delete user account BreadcrumbUserHijack: Hijack user session BreadcrumbSystemMessage: System message BreadcrumbSubmission: Submission -BreadcrumbCourseNews: Course news -BreadcrumbCourseNewsDelete: Delete course news -BreadcrumbCourseEventDelete: Delete course occurrence +BreadcrumbCourseNews: Course type news +BreadcrumbCourseNewsDelete: Delete course type news +BreadcrumbCourseEventDelete: Delete course type occurrence BreadcrumbProfile: Settings -BreadcrumbCourseParticipantInvitation: Invitation to be a course participant +BreadcrumbCourseParticipantInvitation: Invitation to be a course type participant BreadcrumbMaterialArchive: Archive BreadcrumbMaterialFile: File BreadcrumbMaterialVideo: Video @@ -42,7 +42,7 @@ BreadcrumbSheetPseudonym: Pseudonym BreadcrumbSheetCorrectorInvite: Invitation to be a corrector BreadcrumbSheetFile: File BreadcrumbTutorialRegister: Register -BreadcrumbTutorInvite: Invitation to be a tutor +BreadcrumbTutorInvite: Invitation to be a instructor BreadcrumbExamCorrectorInvite: Invitation to be an exam corrector BreadcrumbExamParticipantInvite: Invitation to be an exam participant BreadcrumbExamRegister: Register @@ -57,8 +57,8 @@ BreadcrumbExternalExamUsers: Participants BreadcrumbExternalExamGrades: Exam results BreadcrumbExternalExamStaffInvite: Invitation BreadcrumbExternalExamCorrect: Enter exam results -BreadcrumbParticipantsList: Lists of course participants -BreadcrumbParticipants: Course participants +BreadcrumbParticipantsList: Lists of course type participants +BreadcrumbParticipants: Course type participants BreadcrumbExamAutoOccurrence: Automatic occurrence/room distribution BreadcrumbStorageKey: Generate storage key BreadcrumbMessageHide: Hide @@ -82,7 +82,7 @@ BreadcrumbExamOfficeExams: Exams BreadcrumbExamOfficeFields: Fields of study BreadcrumbExamOfficeUsers: Users BreadcrumbInformation: Information -BreadcrumbInfoLecturerTitle: Information for lecturers +BreadcrumbInfoLecturerTitle: Information for course administrators BreadcrumbLegal: Legal BreadcrumbVersion: Version history BreadcrumbHelp: Support @@ -91,11 +91,11 @@ BreadcrumbInstance: Instance identification BreadcrumbUserDisplayEmail: Email address BreadcrumbProfileData: Personal information BreadcrumbAuthPreds: Authorisation settings -BreadcrumbTermShow: Semesters -BreadcrumbTermCreate: Create new semester -BreadcrumbTermEdit: Edit semester -BreadcrumbTermCurrent: Current semester -BreadcrumbParticipantsIntersect: Common course participants +BreadcrumbTermShow: Years +BreadcrumbTermCreate: Create new year +BreadcrumbTermEdit: Edit year +BreadcrumbTermCurrent: Current year +BreadcrumbParticipantsIntersect: Common course type participants BreadcrumbCourseList: Courses BreadcrumbCourseNew: Create new course BreadcrumbCourseEdit: Edit course @@ -104,14 +104,14 @@ BreadcrumbCourseAddMembers: Add participants BreadcrumbCourseExamOffice: Exam offices BreadcrumbCorrectionsAssign: Assign corrections BreadcrumbSheetList: Exercise sheets -BreadcrumbCourseCommunication: Course message (email) -BreadcrumbTutorialList: Tutorials -BreadcrumbTutorialNew: Create new tutorial +BreadcrumbCourseCommunication: Course type message (email) +BreadcrumbTutorialList: Courses +BreadcrumbTutorialNew: Create new course BreadcrumbCourseDelete: Delete course -BreadcrumbCourseNewsNew: Add course news -BreadcrumbCourseNewsEdit: Edit course news -BreadcrumbCourseEventNew: New course occurrence -BreadcrumbCourseEventEdit: Edit course occurrence +BreadcrumbCourseNewsNew: Add course type news +BreadcrumbCourseNewsEdit: Edit course type news +BreadcrumbCourseEventNew: New course type occurrence +BreadcrumbCourseEventEdit: Edit course type occurrence BreadcrumbExamList: Exams BreadcrumbExamNew: Create new exam BreadcrumbExamEdit: Edit exam @@ -119,9 +119,9 @@ BreadcrumbExamUsers: Participants BreadcrumbExamGrades: Exam results BreadcrumbExamAddMembers: Add exam participants BreadcrumbExamCorrect: Grade exams -BreadcrumbTutorialDelete: Delete tutorial -BreadcrumbTutorialEdit: Edit tutorial -BreadcrumbTutorialComm: Send course message +BreadcrumbTutorialDelete: Delete course +BreadcrumbTutorialEdit: Edit course +BreadcrumbTutorialComm: Send course type message BreadcrumbSheetEdit: Edit exercise sheet BreadcrumbSheetDelete: Delete exercise sheet BreadcrumbSubmissions: Submissions diff --git a/messages/uniworx/utils/navigation/menu/de-de-formal.msg b/messages/uniworx/utils/navigation/menu/de-de-formal.msg index fa2594f03..a253ee93c 100644 --- a/messages/uniworx/utils/navigation/menu/de-de-formal.msg +++ b/messages/uniworx/utils/navigation/menu/de-de-formal.msg @@ -7,7 +7,7 @@ MenuAdminFeaturesHeading: Studiengänge MenuInfoLecturerTitle: Hinweise für Veranstalter:innen MenuInfoLecturerCourses: Veranstaltungen MenuInfoLecturerExercises: Übungsbetrieb -MenuInfoLecturerTutorials: Tutorien +MenuInfoLecturerTutorials: Kurse MenuInfoLecturerExams: Prüfungen MenuCsvOptions: CSV-Optionen MenuCorrectorAssignTitle: Korrektor:in zuweisen @@ -27,13 +27,14 @@ MenuHelp: Hilfe MenuProfile: Anpassen MenuLogin !ident-ok: Login MenuLogout !ident-ok: Logout -MenuCourseList: Kurse -MenuCourseMembers: Kursteilnehmer:innen -MenuCourseAddMembers: Kursteilnehmer:innen hinzufügen -MenuTutorialAddMembers: Tutorium Teilnehmer:innen hinzufügen -MenuCourseCommunication: Kursmitteilung (E‑Mail) +MenuCourseList: Kursarten +MenuCourseIcon: Kurse +MenuCourseMembers: Kursartteilnehmer:innen +MenuCourseAddMembers: Kursartteilnehmer:innen hinzufügen +MenuTutorialAddMembers: Kursteilnehmer:innen hinzufügen +MenuCourseCommunication: Kursartmitteilung (E‑Mail) MenuCourseExamOffice: Prüfungsbeauftragte -MenuTermShow: Semester +MenuTermShow: Jahr MenuSubmissionDelete: Abgabe löschen MenuUsers: Benutzer:in MenuUserAdd: Benutzer:in anlegen @@ -44,10 +45,10 @@ MenuMessageList: Systemnachrichten MenuAdminErrMsg: Fehlermeldung entschlüsseln MenuAdminTokens: Tokens ausstellen MenuProfileData: Persönliche Daten -MenuTermCreate: Neues Semester anlegen -MenuCourseNew: Neuen Kurs anlegen -MenuTermEdit: Semester editieren -MenuTermCurrent: Aktuelles Semester +MenuTermCreate: Neues Jahr anlegen +MenuCourseNew: Neue Kursart anlegen +MenuTermEdit: Jahr editieren +MenuTermCurrent: Aktuelles Jahr MenuCorrection: Korrektur MenuCorrections: Korrekturen MenuCorrectionsOwn: Meine Korrekturen @@ -57,14 +58,14 @@ MenuMaterialList !ident-ok: Material MenuMaterialNew: Neues Material veröffentlichen MenuMaterialEdit: Material bearbeiten MenuMaterialDelete: Material löschen -MenuTutorialList: Tutorien -MenuTutorialNew: Neues Tutorium anlegen +MenuTutorialList: Kurse +MenuTutorialNew: Neuen Kurs anlegen MenuSheetNew: Neues Übungsblatt anlegen MenuSheetCurrent: Aktuelles Übungsblatt MenuSheetOldUnassigned: Abgaben ohne Korrektor:in -MenuCourseEdit: Kurs editieren -MenuCourseClone: Als neuen Kurs klonen -MenuCourseDelete: Kurs löschen +MenuCourseEdit: Kursart editieren +MenuCourseClone: Als neue Kursart klonen +MenuCourseDelete: Kursart löschen MenuSubmissionNew: Abgabe anlegen MenuSubmissionOwn: Abgabe MenuCorrectors: Korrektor:innen @@ -78,8 +79,8 @@ MenuCorrectionsGrade: Korrekturen eintragen MenuCorrectionsAssign: Zuteilung der Korrekturen MenuCorrectionsAssignSheet name@Text: Zuteilung der Korrekturen von #{name} MenuAuthPreds: Authorisierungseinstellungen -MenuTutorialDelete: Tutorium löschen -MenuTutorialEdit: Tutorium editieren +MenuTutorialDelete: Kurs löschen +MenuTutorialEdit: Kurs editieren MenuTutorialComm: Mitteilung an Teilnehmer:innen MenuExamList: Prüfungen MenuExamNew: Neue Prüfung anlegen @@ -92,26 +93,26 @@ MenuExamOfficeExams: Prüfungen MenuExamOfficeFields: Fächer MenuExamOfficeUsers: Benutzer:innen MenuLecturerInvite: Funktionäre hinzufügen -MenuSchoolList: Institute -MenuSchoolNew: Neues Institut anlegen +MenuSchoolList: Bereiche +MenuSchoolNew: Neuen Bereich anlegen MenuExternalExamGrades: Prüfungsleistungen MenuExternalExamUsers: Teilnehmer:innen MenuExternalExamEdit: Bearbeiten MenuExternalExamNew: Neue externe Prüfung MenuExternalExamList: Externe Prüfungen MenuExternalExamCorrect: Prüfungsleistungen eintragen -MenuParticipantsList: Kursteilnehmerlisten -MenuParticipantsIntersect: Überschneidung von Kursteilnehmer:innen +MenuParticipantsList: Kursartteilnehmerlisten +MenuParticipantsIntersect: Überschneidung von Kursartteilnehmer:innen MenuFaq !ident-ok: FAQ MenuSheetPersonalisedFiles: Personalisierte Dateien herunterladen MenuCourseSheetPersonalisedFiles: Vorlage für personalisierte Übungsblatt-Dateien herunterladen MenuAdminCrontab !ident-ok: Crontab MenuGlossary: Begriffsverzeichnis MenuVersion: Versionsgeschichte -MenuCourseNewsNew: Neue Kursnachricht -MenuCourseNewsEdit: Kursnachricht bearbeiten -MenuCourseEventNew: Neuer Kurstermin -MenuCourseEventEdit: Kurstermin bearbeiten +MenuCourseNewsNew: Neue Kursartnachricht +MenuCourseNewsEdit: Kursartnachricht bearbeiten +MenuCourseEventNew: Neuer Kursarttermin +MenuCourseEventEdit: Kursarttermin bearbeiten MenuLanguage: Sprache MenuQualifications: Qualifikationen diff --git a/messages/uniworx/utils/navigation/menu/en-eu.msg b/messages/uniworx/utils/navigation/menu/en-eu.msg index 15242f860..798d1468a 100644 --- a/messages/uniworx/utils/navigation/menu/en-eu.msg +++ b/messages/uniworx/utils/navigation/menu/en-eu.msg @@ -4,10 +4,10 @@ MenuAdminHeading: Administration MenuAdminFeaturesHeading: Features of study -MenuInfoLecturerTitle: Information for lecturers +MenuInfoLecturerTitle: Information for course administrators MenuInfoLecturerCourses: Courses -MenuInfoLecturerExercises: Course Exercises -MenuInfoLecturerTutorials: Tutorials +MenuInfoLecturerExercises: Course type Exercises +MenuInfoLecturerTutorials: Courses MenuInfoLecturerExams: Exams MenuCsvOptions: CSV-options MenuCorrectorAssignTitle: Assign corrector @@ -27,11 +27,12 @@ MenuHelp: Support MenuProfile: Settings MenuLogin: Login MenuLogout: Logout -MenuCourseList: Courses +MenuCourseList: Course types +MenuCourseIcon: Courses MenuCourseMembers: Participants -MenuCourseAddMembers: Add course participants -MenuTutorialAddMembers: Add tutorium participants -MenuCourseCommunication: Course message (email) +MenuCourseAddMembers: Add course type participants +MenuTutorialAddMembers: Add course participants +MenuCourseCommunication: Course type message (email) MenuCourseExamOffice: Exam offices MenuTermShow: Semesters MenuSubmissionDelete: Delete submission @@ -44,10 +45,10 @@ MenuMessageList: System messages MenuAdminErrMsg: Decrypt error message MenuAdminTokens: Issue tokens MenuProfileData: Personal information -MenuTermCreate: Create new semester -MenuCourseNew: Create new course -MenuTermEdit: Edit semester -MenuTermCurrent: Current semester +MenuTermCreate: Create new year +MenuCourseNew: Create new course type +MenuTermEdit: Edit year +MenuTermCurrent: Current year MenuCorrection: Correction MenuCorrections: Corrections MenuCorrectionsOwn: My corrections @@ -57,8 +58,8 @@ MenuMaterialList: Material MenuMaterialNew: Publish new material MenuMaterialEdit: Edit material MenuMaterialDelete: Delete material -MenuTutorialList: Tutorials -MenuTutorialNew: Create new tutorial +MenuTutorialList: Courses +MenuTutorialNew: Create new course MenuSheetNew: Create new exercise sheet MenuSheetCurrent: Current exercise sheet MenuSheetOldUnassigned: Submissions without corrector @@ -79,9 +80,9 @@ MenuCorrectionsGrade: Grade submissions MenuCorrectionsAssign: Assign corrections MenuCorrectionsAssignSheet name: Assign corrections for #{name} MenuAuthPreds: Authorisation settings -MenuTutorialDelete: Delete tutorial -MenuTutorialEdit: Edit tutorial -MenuTutorialComm: Send course message +MenuTutorialDelete: Delete course +MenuTutorialEdit: Edit course +MenuTutorialComm: Send course type message MenuExamList: Exams MenuExamNew: Create new exam MenuExamEdit: Edit exam @@ -101,18 +102,18 @@ MenuExternalExamEdit: Edit MenuExternalExamNew: New external exam MenuExternalExamList: External exams MenuExternalExamCorrect: Enter exam results -MenuParticipantsList: Lists of course participants -MenuParticipantsIntersect: Common course participants +MenuParticipantsList: Lists of course type participants +MenuParticipantsIntersect: Common course type participants MenuFaq: FAQ MenuSheetPersonalisedFiles: Download personalised sheet files MenuCourseSheetPersonalisedFiles: Download template for personalised sheet files MenuAdminCrontab: Crontab MenuGlossary: Glossary MenuVersion: Version history -MenuCourseNewsNew: Add course news -MenuCourseNewsEdit: Edit course news -MenuCourseEventNew: New course occurrence -MenuCourseEventEdit: Edit course occurrence +MenuCourseNewsNew: Add course type news +MenuCourseNewsEdit: Edit course type news +MenuCourseEventNew: New course type occurrence +MenuCourseEventEdit: Edit course type occurrence MenuLanguage: Language MenuQualifications: Qualifications diff --git a/messages/uniworx/utils/site_layout/de-de-formal.msg b/messages/uniworx/utils/site_layout/de-de-formal.msg index 61b10dd1a..34681feea 100644 --- a/messages/uniworx/utils/site_layout/de-de-formal.msg +++ b/messages/uniworx/utils/site_layout/de-de-formal.msg @@ -22,23 +22,23 @@ HeadingDataProt: Datenschutzerklärung HeadingTermsUse: Nutzungsbedingungen HeadingCopyright: Urheberrecht HeadingImprint: Impressum -HeadingTermsHeading: Semesterübersicht -HeadingTermEditHeading: Semester editieren/anlegen -HeadingTermCurrent: Aktuelles Semester -HeadingTermEditTid tid@TermId: Semester #{tid} editieren -TermCourseListHeading tid@TermId: Kursübersicht #{tid} -TermSchoolCourseListHeading tid@TermId school@SchoolName: Kursübersicht #{tid} für #{school} -CourseListTitle: Alle Kurse -CourseNewHeading: Neuen Kurs anlegen -CourseEditHeading tid@TermId ssh@SchoolId csh@CourseShorthand: Kurs #{tid}-#{ssh}-#{csh} editieren -SubmissionsCourse tid@TermId ssh@SchoolId csh@CourseShorthand: Alle Abgaben Kurs #{tid}-#{ssh}-#{csh} +HeadingTermsHeading: Jahresübersicht +HeadingTermEditHeading: Jahr editieren/anlegen +HeadingTermCurrent: Aktuelles Jahr +HeadingTermEditTid tid@TermId: Jahr #{tid} editieren +TermCourseListHeading tid@TermId: Kursartübersicht #{tid} +TermSchoolCourseListHeading tid@TermId school@SchoolName: Kursartübersicht #{tid} für #{school} +CourseListTitle: Alle Kursarten +CourseNewHeading: Neue Kursart anlegen +CourseEditHeading tid@TermId ssh@SchoolId csh@CourseShorthand: Kursart #{tid}-#{ssh}-#{csh} editieren +SubmissionsCourse tid@TermId ssh@SchoolId csh@CourseShorthand: Alle Abgaben Kursart #{tid}-#{ssh}-#{csh} SubmissionsSheet sheetName@SheetName: Abgaben für #{sheetName} SheetList tid@TermId ssh@SchoolId csh@CourseShorthand: #{tid}-#{ssh}-#{csh} Übersicht Übungsblätter SheetNewHeading tid@TermId ssh@SchoolId csh@CourseShorthand: #{tid}-#{ssh}-#{csh} Neues Übungsblatt anlegen SheetTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName !ident-ok: #{tid}-#{ssh}-#{csh} #{sheetName} SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{tid}-#{ssh}-#{csh}: Neues Übungsblatt SheetEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName} editieren -SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kurs #{tid}-#{ssh}-#{csh} herauslöschen? Alle assoziierten Abgaben und Korrekturen gehen ebenfalls verloren! +SheetDelHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{sheetName} wirklich aus Kursart #{tid}-#{ssh}-#{csh} herauslöschen? Alle assoziierten Abgaben und Korrekturen gehen ebenfalls verloren! SubmissionEditHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName}: Abgabe editieren/anlegen CorrectionHead tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName cid@CryptoFileNameSubmission: #{tid}-#{ssh}-#{csh} #{sheetName}: Korrektur CorrectionsTitle: Zugewiesene Korrekturen @@ -47,9 +47,9 @@ CorrCreate: Abgaben registrieren CorrGrade: Korrekturen eintragen TableHeadingCsvImport: CSV-Import TableHeadingCsvExport: CSV-Export -FavouritesEmptyTip: Hier werden Ihre Kurse, sowie zuletzt besuchte Kurse angezeigt. -FavouritesToggleTip: Der Anzeigemodus für den aktuellen Kurs kann über einen Klick auf das Stern-Symbol zwischen automatisch, permanent und nie gewechselt werden. -FavouritesUnavailableTip: Das Schnellzugriffsmenü für diesen Kurs ist aktuell nicht verfügbar. +FavouritesEmptyTip: Hier werden Ihre Kursarten, sowie zuletzt besuchte Kursarten angezeigt. +FavouritesToggleTip: Der Anzeigemodus für die aktuelle Kursart kann über einen Klick auf das Stern-Symbol zwischen automatisch, permanent und nie gewechselt werden. +FavouritesUnavailableTip: Das Schnellzugriffsmenü für diese Kursart ist aktuell nicht verfügbar. NavigationFavourites: Favoriten ErrorResponseTitleInternalError internalError@Text: Ein interner Fehler ist aufgetreten ErrorResponseTitleInvalidArgs invalidArgs@Texts: Anfrage-Nachricht enthielt ungültige Argumente diff --git a/messages/uniworx/utils/site_layout/en-eu.msg b/messages/uniworx/utils/site_layout/en-eu.msg index 50358068d..d263f8217 100644 --- a/messages/uniworx/utils/site_layout/en-eu.msg +++ b/messages/uniworx/utils/site_layout/en-eu.msg @@ -22,15 +22,15 @@ HeadingDataProt: Data protection HeadingTermsUse: Terms of use HeadingCopyright: Copyright HeadingImprint: Imprint -HeadingTermsHeading: Semesters -HeadingTermEditHeading: Edit semester -HeadingTermCurrent: Current semester -HeadingTermEditTid tid: Edit semester #{tid} +HeadingTermsHeading: Years +HeadingTermEditHeading: Edit year +HeadingTermCurrent: Current year +HeadingTermEditTid tid: Edit year #{tid} TermCourseListHeading tid: Courses #{tid} TermSchoolCourseListHeading tid school: Courses #{tid}, #{school} CourseListTitle: All courses -CourseNewHeading: Create new course -CourseEditHeading tid ssh csh: Edit course #{tid}-#{ssh}-#{csh} +CourseNewHeading: Create new course type +CourseEditHeading tid ssh csh: Edit course type #{tid}-#{ssh}-#{csh} SubmissionsCourse tid ssh csh: All submissions for Course #{tid}-#{ssh}-#{csh} SubmissionsSheet sheetName: Submissions for #{sheetName} SheetList tid ssh csh : #{tid}-#{ssh}-#{csh} Sheet Overview @@ -38,7 +38,7 @@ SheetNewHeading tid ssh csh : #{tid}-#{ssh}-#{csh} New Exercise Sheet SheetTitle tid@TermId ssh@SchoolId csh@CourseShorthand sheetName@SheetName: #{tid}-#{ssh}-#{csh} #{sheetName} SheetTitleNew tid@TermId ssh@SchoolId csh@CourseShorthand : #{tid}-#{ssh}-#{csh}: New sheet SheetEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} Edit #{sheetName} -SheetDelHead tid ssh csh sheetName: Do you really want to delete sheet #{sheetName} from course #{tid}-#{ssh}-#{csh}? Any associated submissions and corrections will be lost! +SheetDelHead tid ssh csh sheetName: Do you really want to delete sheet #{sheetName} from course type #{tid}-#{ssh}-#{csh}? Any associated submissions and corrections will be lost! SubmissionEditHead tid ssh csh sheetName: #{tid}-#{ssh}-#{csh} #{sheetName}: Edit/Create submission CorrectionHead tid ssh csh sheetName cid: #{tid}-#{ssh}-#{csh} #{sheetName}: Marking CorrectionsTitle: Assigned corrections @@ -48,8 +48,8 @@ CorrGrade: Mark submissions TableHeadingCsvImport: CSV import TableHeadingCsvExport: CSV export FavouritesEmptyTip: Your courses and recently visited courses are shown here. -FavouritesToggleTip: The display mode for the current course can be changed between automatic, permanent and never with a click on the star symbol. -FavouritesUnavailableTip: Quick Actions for this course are currently not available. +FavouritesToggleTip: The display mode for the current course type can be changed between automatic, permanent and never with a click on the star symbol. +FavouritesUnavailableTip: Quick Actions for this course type are currently not available. NavigationFavourites: Favourites ErrorResponseTitleInternalError internalError: An internal error occurred ErrorResponseTitleInvalidArgs invalidArgs: Request contained invalid arguments diff --git a/messages/uniworx/utils/table_column/de-de-formal.msg b/messages/uniworx/utils/table_column/de-de-formal.msg index c3247ecf5..b9e575dda 100644 --- a/messages/uniworx/utils/table_column/de-de-formal.msg +++ b/messages/uniworx/utils/table_column/de-de-formal.msg @@ -12,15 +12,15 @@ TableStudyFeatureType !empty-ok: TableStudyFeatureValid: Aktiv TableStudyFeatureUpdate: Abgeglichen TableHeadingFilter !ident-ok: Filter -TableTerm !ident-ok: Semester -TableCourseSchool: Institut +TableTerm !ident-ok: Jahr +TableCourseSchool: Bereich TableSubmissionGroup: Feste Abgabegruppe TableNoSubmissionGroup: Keine feste Abgabegruppe TableMatrikelNr: AVS Nr TableSex: Geschlecht TableBirthday: Geburtsdatum -TableSchool: Institut -TableCourse: Kurs +TableSchool: Bereich +TableCourse: Kursart TableCourseMembers: Teilnehmer:innen TableExamOccurrence: Termin/Raum TableExamName !ident-ok: Name @@ -45,7 +45,7 @@ TableHasCorrector: Korrektor zugeteilt TableAchievedOf achieved@Points possible@Points: #{achieved} von #{possible} TablePassed: Bestanden TableNotPassed: Nicht bestanden -TableTutorialTutors: Tutoren +TableTutorialTutors: Ausbilder TableTutorialName: Bezeichnung TableTutorialType: Art TableTutorialRoom: Regulärer Raum @@ -54,6 +54,7 @@ TableTutorialRoomIsUnset !ident-ok: — TableTutorialRoomIsHidden: Raum wird nur Teilnehmern angezeigt TableTutorialTime: Zeit TableTutorialDeregisterUntil: Abmeldungen bis +TableTutorialFirstDay: Starttag TableActionsHead: Aktionen TableNoFilter: Keine Einschränkung TableUserMatriculation: ASV Nummer diff --git a/messages/uniworx/utils/table_column/en-eu.msg b/messages/uniworx/utils/table_column/en-eu.msg index 5ff701e6a..5187d80dc 100644 --- a/messages/uniworx/utils/table_column/en-eu.msg +++ b/messages/uniworx/utils/table_column/en-eu.msg @@ -8,11 +8,11 @@ TableEmail: Email TableStudyFeatureType: TableStudyFeatureValid: Valid TableStudyFeatureUpdate: Updated -TableStudyFeatureAge: Semester +TableStudyFeatureAge: Semesters TableStudyFeatureDegree: Degree TableStudyTerm: Field of study TableHeadingFilter: Filter -TableTerm: Semester +TableTerm: Year TableCourseSchool: Department TableSubmissionGroup: Registered submission group TableNoSubmissionGroup: No registered submission group @@ -45,7 +45,7 @@ TableHasCorrector: Corrector assigned TableAchievedOf achieved possible: #{achieved} of #{possible} TablePassed: Passed TableNotPassed: Failed -TableTutorialTutors: Tutors +TableTutorialTutors: Instructors TableTutorialName: Name TableTutorialType: Type TableTutorialRoom: Regular room @@ -53,6 +53,7 @@ TableTutorialRoomHidden: Room only for participants TableTutorialRoomIsUnset: — TableTutorialRoomIsHidden: Room is only displayed to participants TableTutorialDeregisterUntil: Deregister until +TableTutorialFirstDay: Start date TableActionsHead: Actions TableTutorialTime: Time TableNoFilter: No restriction diff --git a/messages/uniworx/utils/table_pagination/de-de-formal.msg b/messages/uniworx/utils/table_pagination/de-de-formal.msg index e58be7183..30668cc18 100644 --- a/messages/uniworx/utils/table_pagination/de-de-formal.msg +++ b/messages/uniworx/utils/table_pagination/de-de-formal.msg @@ -27,7 +27,7 @@ CsvColumnsExplanationsTip: Bedeutung und Format der in der CSV-Datei enthaltenen CsvExportExample: Beispiel-CSV exportieren CsvExampleData: Beispiel-Datei CourseSortingOnlyLoggedIn: Das Benutzerinterface zur Sortierung dieser Tabelle ist nur für eingeloggte Benutzer aktiv -LecturersForN n@Int: #{pluralDE n "Dozent" "Dozenten"} +LecturersForN n@Int: #{pluralDE n "Kursverwalter" "Kursverwaltende"} Registered: Angemeldet Registration: Anmeldung TableCourseDescription: Beschreibung diff --git a/messages/uniworx/utils/table_pagination/en-eu.msg b/messages/uniworx/utils/table_pagination/en-eu.msg index 13720632d..89bcf58fb 100644 --- a/messages/uniworx/utils/table_pagination/en-eu.msg +++ b/messages/uniworx/utils/table_pagination/en-eu.msg @@ -27,7 +27,7 @@ CsvColumnsExplanationsTip: Meaning and format of the columns contained in import CsvExportExample: Export example CSV CsvExampleData: Example data CourseSortingOnlyLoggedIn: The user interface for sorting this table is only active for logged in users -LecturersForN n: #{pluralEN n "Lecturer" "Lecturers"} +LecturersForN n: #{pluralENs n "Course administrator"} Registered: Enrolled Registration: Enrolment TableCourseDescription: Description diff --git a/messages/uniworx/utils/utils/de-de-formal.msg b/messages/uniworx/utils/utils/de-de-formal.msg index 1d5b9d184..13bae27f0 100644 --- a/messages/uniworx/utils/utils/de-de-formal.msg +++ b/messages/uniworx/utils/utils/de-de-formal.msg @@ -4,26 +4,26 @@ #communication.hs RecipientCustom: Weitere Empfänger:innen -RGCourseParticipants: Kursteilnehmer:innen +RGCourseParticipants: Kursartteilnehmer:innen RGCourseLecturers: Kursverwalter:innen RGCourseCorrectors: Korrektor:innen -RGCourseTutors: Tutor:innen -RGCourseParticipantsInTutorial: Kursteilnehmer:innen, die in mindestens einem Tutorium angemeldet sind +RGCourseTutors: Ausbilder:innen +RGCourseParticipantsInTutorial: Kursartteilnehmer:innen, die in mindestens einem Kurs angemeldet sind RGCourseUnacceptedApplicants: Nicht akzeptierte Bewerber:innen RecipientToggleAll: Alle/Keine CommCourseTestSubject customSubject@Text !ident-ok: [TEST] #{customSubject} -UtilCommCourseSubject: Kursmitteilung +UtilCommCourseSubject: Kursartmitteilung CommRecipients: Empfänger:innen CommRecipientsTip: Sie selbst erhalten immer eine Kopie der Nachricht CommRecipientsList: Die an Sie selbst verschickte Kopie der Nachricht wird, zu Archivierungszwecken, eine vollständige Liste aller Empfänger:innen enthalten. Die Empfängerliste wird im CSV-Format an die E-Mail angehängt. Andere Empfänger:innen erhalten die Liste nicht. Bitte entfernen Sie dementsprechend den Anhang bevor Sie die E-Mail weiterleiten oder anderweitig mit Dritten teilen. UtilEMail: E-Mail UtilMultiEmailFieldTip: Es sind mehrere, Komma-separierte, E-Mail-Adressen möglich -RGTutorialParticipants tutn@TutorialName: Tutorium-Teilnehmer:innen (#{tutn}) +RGTutorialParticipants tutn@TutorialName: Kursteilnehmer:innen (#{tutn}) RGExamRegistered examn@ExamName: Angemeldet zur Prüfung „#{examn}“ RGSheetSubmittor shn@SheetName: Abgebende für das Übungsblatt „#{shn}“ CommSubject: Betreff CommAttachments: Anhänge -CommAttachmentsTip: Im Allgemeinen ist es vorzuziehen Dateien, die Sie mit den Empfängern teilen möchten, als Material hochzuladen (und ggf. in der Nachricht zu verlinken). So ist die Datei für die Empfänger dauerhaft abrufbar und auch Personen, die sich z.B. erst später zum Kurs anmelden, haben Zugriff auf die Datei. +CommAttachmentsTip: Im Allgemeinen ist es vorzuziehen Dateien, die Sie mit den Empfängern teilen möchten, als Material hochzuladen (und ggf. in der Nachricht zu verlinken). So ist die Datei für die Empfänger dauerhaft abrufbar und auch Personen, die sich z.B. erst später zur Kursart anmelden, haben Zugriff auf die Datei. CommSuccess n@Int: Nachricht wurde an #{n} Empfänger versandt CommTestSuccess: Nachricht wurde zu Testzwecken nur an Sie selbst versandt @@ -117,7 +117,7 @@ SheetGradingPassing': Bestehen #utils.hs DayIsAHoliday tid@TermId name@Text date@Text: "#{name}" (#{date}) ist ein Feiertag DayIsOutOfLecture tid@TermId name@Text date@Text: "#{name}" (#{date}) ist außerhalb der Vorlesungszeit des #{tid} -DayIsOutOfTerm tid@TermId name@Text date@Text: "#{name}" (#{date}) liegt nicht im Semester #{tid} +DayIsOutOfTerm tid@TermId name@Text date@Text: "#{name}" (#{date}) liegt nicht im Jahr #{tid} UnauthorizedRedirect: Die angeforderte Seite existiert nicht oder Sie haben keine Berechtigung, die angeforderte Seite zu sehen. EncodedSecretBoxCiphertextTooShort: Verschlüsselte Daten zu kurz um valide zu sein diff --git a/messages/uniworx/utils/utils/en-eu.msg b/messages/uniworx/utils/utils/en-eu.msg index 9162d42f4..27a7eecad 100644 --- a/messages/uniworx/utils/utils/en-eu.msg +++ b/messages/uniworx/utils/utils/en-eu.msg @@ -4,26 +4,26 @@ #communication.hs RecipientCustom: Custom recipients -RGCourseParticipants: Course participants +RGCourseParticipants: Course type participants RGCourseLecturers: Course administrators -RGCourseCorrectors: Course correctors -RGCourseTutors: Course tutors -RGCourseParticipantsInTutorial: Course participants who are registered for at least one tutorial +RGCourseCorrectors: Course type correctors +RGCourseTutors: Course instructors +RGCourseParticipantsInTutorial: Course type participants who are registered for at least one course RGCourseUnacceptedApplicants: Applicants not accepted RecipientToggleAll: All/None CommCourseTestSubject customSubject: [TEST] #{customSubject} -UtilCommCourseSubject: Course message +UtilCommCourseSubject: Course type message CommRecipients: Recipients CommRecipientsTip: You always receive a copy of the message CommRecipientsList: For archival purposes the copy of the message sent to you will contain a complete list of all recipients. The list of recipients will be attached to the email in CSV-format. Other recipients do not receive the list. Thus, please remove the attachment before you forward the email or otherwise share it with third parties. UtilEMail: Email UtilMultiEmailFieldTip: Multiple emails addresses may be specified (comma-separated) -RGTutorialParticipants tutn: Tutorial participants (#{tutn}) +RGTutorialParticipants tutn: Course participants (#{tutn}) RGExamRegistered examn: Registered for exam “#{examn}” RGSheetSubmittor shn: Submitted for exercise sheet “#{shn}” CommSubject: Subject CommAttachments: Attachments -CommAttachmentsTip: In general it is preferable to upload files as course material instead of sending them as attachments. You can then link to the material from the message. The file is then permanently accessable to the recipients and to persons that, for example, register for the Course at a later date. +CommAttachmentsTip: In general it is preferable to upload files as course type material instead of sending them as attachments. You can then link to the material from the message. The file is then permanently accessable to the recipients and to persons that, for example, register for the Course type at a later date. CommSuccess n: Message was sent to #{n} #{pluralEN n "recipient" "recipients"} CommTestSuccess: Message was sent only to yourself for testing purposes diff --git a/models/avs.model b/models/avs.model index b9f77cdd7..7a8a59cc0 100644 --- a/models/avs.model +++ b/models/avs.model @@ -18,6 +18,7 @@ UserAvs user UserId noPerson Int default=0 -- only needed for manual communication with personnel from Ausweisverwaltungsstelle lastSynch UTCTime default=now() + lastSynchError Text Maybe UniqueUserAvsUser user UniqueUserAvsId personId deriving Generic Show @@ -32,3 +33,10 @@ UserAvsCard lastSynch UTCTime -- UniqueAvsCard cardNo -- Note: cardNo is not unique; invalid cardNo may be reissued to different persons deriving Generic + +AvsSync + user UserId -- Note: we need to lookup UserAvs Entity anyway, so no benefit from storing AvsPersonId here + creationTime UTCTime + pause Day Maybe + UniqueAvsSyncUser user + deriving Generic \ No newline at end of file diff --git a/models/courses.model b/models/courses.model index 95fb7cf60..ded2013dd 100644 --- a/models/courses.model +++ b/models/courses.model @@ -57,7 +57,7 @@ Lecturer -- course ownership UniqueLecturer user course -- note: multiple lecturers per course are allowed, but no duplicated rows in this table deriving Generic CourseParticipant -- course enrolement - course CourseId + course CourseId OnDeleteCascade OnUpdateCascade user UserId registration UTCTime -- time of last enrolement for this course field StudyFeaturesId Maybe MigrationOnly @@ -73,7 +73,7 @@ CourseParticipant -- course enrolement -- editor UserId -- who edited this note last -- UniqueCourseUserNote user course CourseUserNote -- lecturers of a specific course may share a text note on each enrolled student - course CourseId + course CourseId OnDeleteCascade OnUpdateCascade user UserId note StoredMarkup -- arbitrary user-defined text; visible only to lecturer of this course UniqueCourseUserNote user course @@ -85,14 +85,14 @@ CourseUserNoteEdit -- who edited a participants course note when deriving Generic CourseUserExamOfficeOptOut - course CourseId + course CourseId OnDeleteCascade OnUpdateCascade user UserId school SchoolId UniqueCourseUserExamOfficeOptOut course user school deriving Generic CourseQualification - course CourseId + course CourseId OnDeleteCascade OnUpdateCascade qualification QualificationId sortOrder Int default=0 --TODO: not yet used in Handler.Course.Users.makeCourseUserTable UniqueCourseQualification course qualification diff --git a/models/exams.model b/models/exams.model index 969b85455..e7dae4212 100644 --- a/models/exams.model +++ b/models/exams.model @@ -3,7 +3,7 @@ -- SPDX-License-Identifier: AGPL-3.0-or-later Exam - course CourseId + course CourseId OnDeleteCascade OnUpdateCascade name ExamName gradingRule ExamGradingRule Maybe bonusRule ExamBonusRule Maybe diff --git a/models/lms.model b/models/lms.model index 8448f20a6..b25ba00f8 100644 --- a/models/lms.model +++ b/models/lms.model @@ -11,10 +11,10 @@ Qualification validDuration Int Maybe -- > 0, qualification is valid indefinitely or for a specified number of months, use with addMonthsDay auditDuration Int Maybe -- > 0, number of months to keep audit log and LmsUserIdents; or indefinitely (dangerous, since LmsIdents may run out) refreshWithin CalendarDiffDays Maybe -- notify users about renewal within this number of month/days before expiry; to be used with addGregorianDurationClip + refreshReminder CalendarDiffDays Maybe -- send a second notification about renewal within this number of month/days before expiry elearningStart Bool -- automatically schedule e-refresher - -- elearningOnly Bool -- successful E-learing automatically increases validity. NO! - -- refreshInvitation StoredMarkup -- hard-coded I18N-MSGs used instead, but displayed on qualification page NO! - -- expiryNotification StoredMarkup Maybe -- configurable user-profile-notifcations are used instead NO! + -- elearningOnly Bool -- successful E-learing automatically increases validity. NO! + expiryNotification Bool default=true -- should expiryNotification be generated for this qualification? avsLicence AvsLicence Maybe -- if set, valid QualificationUsers are synchronized to AVS as a driving licence sapId Text Maybe -- if set, valid QualificationUsers with userCompanyPersonalNumber are transmitted via SAP interface under this id SchoolQualificationShort school shorthand -- must be unique per school and shorthand diff --git a/models/tutorials.model b/models/tutorials.model index 0a8558f29..be27d6a87 100644 --- a/models/tutorials.model +++ b/models/tutorials.model @@ -16,6 +16,7 @@ Tutorial json deregisterUntil UTCTime Maybe lastChanged UTCTime default=now() tutorControlled Bool default=false + firstDay Day Maybe -- to be computed from time, but needed for sorting within DB UniqueTutorial course name deriving Generic Tutor diff --git a/models/users.model b/models/users.model index 38305c4f0..8a686feac 100644 --- a/models/users.model +++ b/models/users.model @@ -52,6 +52,7 @@ User json -- Each Uni2work user has a corresponding row in this table; create examOfficeGetLabels Bool default=true -- whether labels should be displayed for exam results by default UniqueAuthentication ident -- Column 'ident' can be used as a row-key in this table UniqueEmail email -- Column 'email' can be used as a row-key in this table + UniqueLdapPrimaryKey ldapPrimaryKey !force -- Column 'ldapPrimaryKey' is either empty or contains a unique value deriving Show Eq Ord Generic -- Haskell-specific settings for runtime-value representing a row in memory UserFunction -- Administratively assigned functions (lecturer, admin, evaluation, ...) diff --git a/nix/docker/demo-version.json b/nix/docker/demo-version.json index ca34cd277..afe4fccef 100644 --- a/nix/docker/demo-version.json +++ b/nix/docker/demo-version.json @@ -1,3 +1,3 @@ { - "version": "27.4.6" + "version": "27.4.11" } diff --git a/nix/docker/version.json b/nix/docker/version.json index ca34cd277..afe4fccef 100644 --- a/nix/docker/version.json +++ b/nix/docker/version.json @@ -1,3 +1,3 @@ { - "version": "27.4.6" + "version": "27.4.11" } diff --git a/package-lock.json b/package-lock.json index de776ba53..c2dc210aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "uni2work", - "version": "27.4.6", + "version": "27.4.11", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c36c4aab0..6eccdb0b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uni2work", - "version": "27.4.6", + "version": "27.4.11", "description": "", "keywords": [], "author": "", diff --git a/package.yaml b/package.yaml index 67710a91d..1791191ce 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: uniworx -version: 27.4.6 +version: 27.4.11 dependencies: - base - yesod diff --git a/src/Database/Esqueleto/Utils.hs b/src/Database/Esqueleto/Utils.hs index d93d0d5ed..66f23b105 100644 --- a/src/Database/Esqueleto/Utils.hs +++ b/src/Database/Esqueleto/Utils.hs @@ -10,6 +10,7 @@ module Database.Esqueleto.Utils , vals, justVal, justValList, toValues , isJust, alt , isInfixOf, hasInfix + , isPrefixOf_, hasPrefix_ , strConcat, substring , (=?.), (?=.) , (=~.), (~=.) @@ -154,9 +155,9 @@ alt :: PersistField typ => E.SqlExpr (E.Value (Maybe typ)) -> E.SqlExpr (E.Value -- alt a b = E.case_ [(isJust a, a), (isJust b, b)] b alt a b = E.coalesce [a,b] -infix 4 `isInfixOf`, `hasInfix` +infix 4 `isInfixOf`, `hasInfix`, `isPrefixOf_`, `hasPrefix_` --- | Check if the first string is contained in the text derived from the second argument +-- | Check if the first string is contained in the text derived from the second argument (case-insensitive) isInfixOf :: ( E.SqlString s1 , E.SqlString s2 ) @@ -169,6 +170,20 @@ hasInfix :: ( E.SqlString s1 => E.SqlExpr (E.Value s2) -> E.SqlExpr (E.Value s1) -> E.SqlExpr (E.Value Bool) hasInfix = flip isInfixOf +-- | Check if the first string is a prefix of the text derived from the second argument (case-insensitive) +isPrefixOf_ :: ( E.SqlString s1 + , E.SqlString s2 + ) + => E.SqlExpr (E.Value s1) -> E.SqlExpr (E.Value s2) -> E.SqlExpr (E.Value Bool) +isPrefixOf_ needle strExpr = E.castString strExpr `E.ilike` needle E.++. (E.%) + +hasPrefix_ :: ( E.SqlString s1 + , E.SqlString s2 + ) + => E.SqlExpr (E.Value s2) -> E.SqlExpr (E.Value s1) -> E.SqlExpr (E.Value Bool) +hasPrefix_ = flip isPrefixOf_ + + infixl 6 `strConcat` strConcat :: E.SqlString s diff --git a/src/Foundation/Navigation.hs b/src/Foundation/Navigation.hs index 047d17312..cfefd462f 100644 --- a/src/Foundation/Navigation.hs +++ b/src/Foundation/Navigation.hs @@ -681,7 +681,7 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the { navHeaderRole = NavHeaderPrimary , navIcon = IconMenuCourseList , navLink = NavLink - { navLabel = MsgMenuCourseList + { navLabel = MsgMenuCourseIcon , navRoute = CourseListR , navAccess' = NavAccessTrue , navType = NavTypeLink { navModal = False } @@ -689,30 +689,30 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navForceActive = False } } - , return NavHeader - { navHeaderRole = NavHeaderPrimary - , navIcon = IconMenuCorrections - , navLink = NavLink - { navLabel = MsgMenuCorrections - , navRoute = CorrectionsR - , navAccess' = NavAccessTrue - , navType = NavTypeLink { navModal = False } - , navQuick' = mempty - , navForceActive = False - } - } - , return NavHeader - { navHeaderRole = NavHeaderPrimary - , navIcon = IconMenuExams - , navLink = NavLink - { navLabel = MsgMenuExamOfficeExams - , navRoute = ExamOfficeR EOExamsR - , navAccess' = NavAccessTrue - , navType = NavTypeLink { navModal = False } - , navQuick' = mempty - , navForceActive = False - } - } + -- , return NavHeader + -- { navHeaderRole = NavHeaderPrimary + -- , navIcon = IconMenuCorrections + -- , navLink = NavLink + -- { navLabel = MsgMenuCorrections + -- , navRoute = CorrectionsR + -- , navAccess' = NavAccessTrue + -- , navType = NavTypeLink { navModal = False } + -- , navQuick' = mempty + -- , navForceActive = False + -- } + -- } + -- , return NavHeader + -- { navHeaderRole = NavHeaderPrimary + -- , navIcon = IconMenuExams + -- , navLink = NavLink + -- { navLabel = MsgMenuExamOfficeExams + -- , navRoute = ExamOfficeR EOExamsR + -- , navAccess' = NavAccessTrue + -- , navType = NavTypeLink { navModal = False } + -- , navQuick' = mempty + -- , navForceActive = False + -- } + -- } , return NavHeader { navHeaderRole = NavHeaderPrimary , navIcon = IconMenuQualification @@ -849,6 +849,22 @@ defaultLinks = fmap catMaybes . mapM runMaybeT $ -- Define the menu items of the , navQuick' = mempty , navForceActive = False } + , NavLink + { navLabel = MsgMenuCorrections + , navRoute = CorrectionsR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } + , NavLink + { navLabel = MsgMenuExamOfficeExams + , navRoute = ExamOfficeR EOExamsR + , navAccess' = NavAccessTrue + , navType = NavTypeLink { navModal = False } + , navQuick' = mempty + , navForceActive = False + } , NavLink { navLabel = MsgMenuExternalExamList , navRoute = EExamListR diff --git a/src/Foundation/Yesod/Auth.hs b/src/Foundation/Yesod/Auth.hs index b3fbced9b..efabadc80 100644 --- a/src/Foundation/Yesod/Auth.hs +++ b/src/Foundation/Yesod/Auth.hs @@ -263,8 +263,8 @@ decodeUser now UserDefaultConf{..} upsertMode ldapData = do userEmail <- if -- TODO: refactor! NOTE: LDAP doesnt know email for all users; we use userPrincialName instead; however validEmail refutes `E return $ CI.mk userEmail - -- | userEmail : _ <- mapMaybe (assertM validEmail . either (const Nothing) Just . Text.decodeUtf8') (lookupSome ldapMap $ toList ldapUserEmail) -- TOO STRONG, see above! - -- -> return $ CI.mk userEmail + -- | userEmail : _ <- mapMaybe (assertM validEmail . either (const Nothing) Just . Text.decodeUtf8') (lookupSome ldapMap $ toList ldapUserEmail) -- TOO STRONG, see above! + -- -> return $ CI.mk userEmail | otherwise -> throwM CampusUserInvalidEmail diff --git a/src/Handler/Admin.hs b/src/Handler/Admin.hs index 227df595f..3775b0359 100644 --- a/src/Handler/Admin.hs +++ b/src/Handler/Admin.hs @@ -41,9 +41,9 @@ getAdminR = redirect AdminProblemsR getAdminProblemsR :: Handler Html getAdminProblemsR = do now <- liftIO getCurrentTime - let cutOffPrintDays = 7 - cutOffPrintJob = addLocalDays (-cutOffPrintDays) now - cutOffAvsSynch = Just $ addUTCTime (-nominalHour) now -- update at most once per hour + let nowaday = utctDay now + cutOffPrintDays = 7 + cutOffPrintJob = addLocalDays (-cutOffPrintDays) now (usersAreReachable, driversHaveAvsIds, rDriversHaveFs, noStalePrintJobs) <- runDB $ (,,,) <$> areAllUsersReachable @@ -56,7 +56,7 @@ getAdminProblemsR = do (Right AvsLicenceDifferences{..}) -> do let problemIds = avsLicenceDiffRevokeAll <> avsLicenceDiffGrantVorfeld <> avsLicenceDiffRevokeRollfeld <> avsLicenceDiffGrantRollfeld -- mapM_ (queueJob' . flip JobSynchroniseAvsId cutOffAvsSynch) problemIds - runDBJobs . forM_ problemIds $ queueDBJob . flip JobSynchroniseAvsId cutOffAvsSynch + runDBJobs . forM_ problemIds $ queueDBJob . flip JobSynchroniseAvsId (Just nowaday) return $ Right ( Set.size avsLicenceDiffRevokeAll , Set.size avsLicenceDiffGrantVorfeld diff --git a/src/Handler/Admin/Avs.hs b/src/Handler/Admin/Avs.hs index 4246073a4..6c6bba259 100644 --- a/src/Handler/Admin/Avs.hs +++ b/src/Handler/Admin/Avs.hs @@ -44,7 +44,7 @@ single = uncurry Map.singleton -- Button only needed in AVS TEST; further buttons see below -data ButtonAvsTest = BtnCheckLicences -- | BtnSynchLicences +data ButtonAvsTest = BtnCheckLicences -- | BtnSynchLicences deriving (Enum, Eq, Ord, Bounded, Read, Show, Generic) instance Universe ButtonAvsTest instance Finite ButtonAvsTest @@ -546,7 +546,7 @@ mkLicenceTable apidStatus dbtIdent aLic apids = do dbtProj = dbtProjId -- Simple $ \(userAvs, user, qualUsr, quali) -> return (userAvs, user, qualUsr, quali) dbtColonnade = mconcat [ dbSelect (applying _2) id $ return . view (resultUserAvs . _userAvsPersonId) - -- $ \DBRow{dbrOutput=(_,_,apid,_)} -> return apid -- return . view resultAvsPID -- does not type due to traversal + -- (\DBRow{dbrOutput=(_,_,apid,_)} -> return apid -- return . view resultAvsPID) -- does not type due to traversal , colUserNameLink AdminUserR , sortable (Just "avspersonno") (i18nCell MsgAvsPersonNo) $ \(view resultUserAvs -> a) -> avsPersonNoLinkedCell a -- , colUserCompany diff --git a/src/Handler/Admin/Test.hs b/src/Handler/Admin/Test.hs index 3d6fd5b4a..906c941bf 100644 --- a/src/Handler/Admin/Test.hs +++ b/src/Handler/Admin/Test.hs @@ -222,6 +222,8 @@ postAdminTestR = do usrCryptoFileName <- maybeM (return "no-user_id") (fmap toPathPiece . mkCryptoFilnameUser) maybeAuthId usrCryptoUUID <- maybeM (return "no-user_id") (fmap toPathPiece . mkCryptoUUIDUser) maybeAuthId + UniWorX{ appSettings' = AppSettings{..} } <- getYesod + let locallyDefinedPageHeading = [whamlet|Admin TestPage for Uni2work|] siteLayout locallyDefinedPageHeading $ do -- defaultLayout $ do @@ -311,6 +313,18 @@ postAdminTestR = do |] i18n $ MsgPrintDebugForStupid "DebugForStupid" + [whamlet| +
+

Some Active App Settings +
+
appJobCronInterval +
#{tshow appJobCronInterval} +
appSynchroniseLdapUsersWithin +
#{tshow appSynchroniseLdapUsersWithin} +
appSynchroniseAvsUsersWithin +
#{tshow appSynchroniseAvsUsersWithin} + |] + @@ -335,6 +349,7 @@ getAdminTestPdfR = do , qualShort = qual ^. _qualificationShorthand . _CI , qualSchool = qual ^. _qualificationSchool , qualDuration = qual ^. _qualificationValidDuration + , isReminder = False } apcIdent <- letterApcIdent letter encRecipient now renderLetterPDF usr letter apcIdent >>= \case diff --git a/src/Handler/Course/Delete.hs b/src/Handler/Course/Delete.hs index eae56855a..5fc16849f 100644 --- a/src/Handler/Course/Delete.hs +++ b/src/Handler/Course/Delete.hs @@ -17,8 +17,20 @@ import qualified Data.Set as Set getCDeleteR, postCDeleteR :: TermId -> SchoolId -> CourseShorthand -> Handler Html getCDeleteR = postCDeleteR postCDeleteR tid ssh csh = do - Entity cId _ <- runDB . getBy404 $ TermSchoolCourseShort tid ssh csh - deleteR $ (courseDeleteRoute $ Set.singleton cId) - { drAbort = SomeRoute $ CourseR tid ssh csh CShowR - , drSuccess = SomeRoute $ TermSchoolCourseListR tid ssh - } + (cId, activeParticipants, existExams) <- runDB $ do + Entity cId _ <- getBy404 $ TermSchoolCourseShort tid ssh csh + activeParticipants <- exists [CourseParticipantState ==. CourseParticipantActive, CourseParticipantCourse ==. cId] + existExams <- exists [ExamCourse ==. cId] + return (cId, activeParticipants, existExams) + if + | activeParticipants -> do + addMessageI Error MsgCourseDeleteActiveParticipants + redirect $ CourseR tid ssh csh CUsersR + | existExams -> do + addMessageI Error MsgCourseDeleteExistExams + redirect $ CourseR tid ssh csh CExamListR + | otherwise -> + deleteR $ (courseDeleteRoute $ Set.singleton cId) + { drAbort = SomeRoute $ CourseR tid ssh csh CShowR + , drSuccess = SomeRoute $ TermSchoolCourseListR tid ssh + } diff --git a/src/Handler/Course/ParticipantInvite.hs b/src/Handler/Course/ParticipantInvite.hs index e129b9d53..4b79d8c86 100644 --- a/src/Handler/Course/ParticipantInvite.hs +++ b/src/Handler/Course/ParticipantInvite.hs @@ -1,7 +1,9 @@ --- SPDX-FileCopyrightText: 2022 Sarah Vaupel +-- SPDX-FileCopyrightText: 2022-23 Sarah Vaupel , Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later +{-# LANGUAGE TypeApplications #-} + module Handler.Course.ParticipantInvite ( getCAddUserR, postCAddUserR , getTAddUserR, postTAddUserR @@ -20,15 +22,37 @@ import Data.Map ((!)) import qualified Data.Map as Map import qualified Data.Time.Zones as TZ import qualified Data.Set as Set +import qualified Data.Text as Text import Control.Monad.Except (MonadError(..)) import Generics.Deriving.Monoid (memptydefault, mappenddefault) +-- import Database.Esqueleto.Experimental ((:&)(..)) +import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma +import qualified Database.Esqueleto.Utils as E + +import Utils.Occurrences + type UserSearchKey = Text -type TutorialIdent = CI Text +type TutorialType = CI Text +defaultTutorialType :: TutorialType +defaultTutorialType = "Schulung" + +tutorialTypeSeparator :: TutorialType +tutorialTypeSeparator = "_" + +tutorialTemplateNames :: Maybe TutorialType -> [TutorialType] +tutorialTemplateNames Nothing = ["Vorlage", "Template"] +tutorialTemplateNames (Just name) = [prefixes <> suffixes | prefixes <- tutorialTemplateNames Nothing, suffixes <- [mempty, tutorialTypeSeparator <> name]] + +tutorialDefaultName :: Maybe TutorialType -> Day -> TutorialName +tutorialDefaultName Nothing = CI.mk . tshow -- Don't use user date display setting, so that tutorial default names conform to all users +tutorialDefaultName (Just ttyp) = + let prefix = CI.mk $ snd $ Text.breakOnEnd (CI.original tutorialTypeSeparator) $ CI.original ttyp + in ((prefix <> tutorialTypeSeparator) <>) . tutorialDefaultName Nothing data ButtonCourseRegisterMode = BtnCourseRegisterConfirm | BtnCourseRegisterAbort deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic) @@ -50,7 +74,7 @@ instance Button UniWorX ButtonCourseRegisterMode where data CourseRegisterAction = CourseRegisterActionAddParticipant | CourseRegisterActionAddTutorialMember --- | CourseRegisterActionUnknownPerson +-- | CourseRegisterActionUnknownPerson deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic) instance Universe CourseRegisterAction instance Finite CourseRegisterAction @@ -63,9 +87,9 @@ data CourseRegisterActionData | CourseRegisterActionAddTutorialMemberData { crActIdent :: UserSearchKey , crActUser :: (UserId, User) - , crActTutorial :: TutorialIdent + , crActTutorial :: (Maybe TutorialName, Maybe TutorialType, Maybe Day) } --- | CourseRegisterActionUnknownPersonData -- pseudo-action; just for display +-- | CourseRegisterActionUnknownPersonData -- pseudo-action; just for display -- { crActUnknownPersonIdent :: Text -- } deriving (Eq, Ord, Show, Generic) @@ -97,7 +121,7 @@ courseRegisterRenderAction act = [whamlet|^{userWidget (view _2 (crActUser act)) data AddUserRequest = AddUserRequest { auReqUsers :: Set UserSearchKey - , auReqTutorial :: Maybe TutorialIdent + , auReqTutorial :: Maybe (Maybe TutorialName, Maybe TutorialType, Maybe Day) } deriving (Eq, Ord, Read, Show, Generic) @@ -121,38 +145,77 @@ getCAddUserR, postCAddUserR :: TermId -> SchoolId -> CourseShorthand -> Handler getCAddUserR = postCAddUserR postCAddUserR tid ssh csh = do today <- localDay . TZ.utcToLocalTimeTZ appTZ <$> liftIO getCurrentTime - postTAddUserR tid ssh csh (CI.mk $ tshow today) -- Don't use user date display setting, so that tutorial default names conform to all users + handleAddUserR tid ssh csh (Right today) Nothing + -- postTAddUserR tid ssh csh (CI.mk $ tshow today) -- Don't use user date display setting, so that tutorial default names conform to all users getTAddUserR, postTAddUserR :: TermId -> SchoolId -> CourseShorthand -> TutorialName -> Handler Html getTAddUserR = postTAddUserR -postTAddUserR tid ssh csh tut = do - cid <- runDB . getKeyBy404 $ TermSchoolCourseShort tid ssh csh +postTAddUserR tid ssh csh tutn = handleAddUserR tid ssh csh (Left tutn) Nothing + + +handleAddUserR :: TermId -> SchoolId -> CourseShorthand -> Either TutorialName Day -> Maybe TutorialType -> Handler Html +handleAddUserR tid ssh csh tdesc ttyp = do + (cid, tutTypes, tutNameSuggestions) <- runDB $ do + let plainTemplates = tutorialTemplateNames Nothing + cid <- getKeyBy404 $ TermSchoolCourseShort tid ssh csh + tutTypes <- E.select $ E.distinct $ do + tutorial <- E.from $ E.table @Tutorial + let tuTyp = tutorial E.^. TutorialType + E.where_ $ tutorial E.^. TutorialCourse E.==. E.val cid + E.orderBy [E.asc tuTyp] + return tuTyp + let typeSet = Set.fromList [ maybe t CI.mk $ Text.stripPrefix temp_sep $ CI.original t + | temp <- plainTemplates + , let temp_sep = CI.original (temp <> tutorialTypeSeparator) + , E.Value t <- tutTypes + ] + tutNames <- E.select $ do + tutorial <- E.from $ E.table @Tutorial + let tuName = tutorial E.^. TutorialName + E.where_ $ tutorial E.^. TutorialCourse E.==. E.val cid + E.&&. E.isJust (tutorial E.^. TutorialFirstDay) + E.&&. E.not_ (E.any (E.hasPrefix_ (tutorial E.^. TutorialType) . E.val) plainTemplates) + E.orderBy [E.desc $ tutorial E.^. TutorialFirstDay, E.asc tuName] + E.limit 7 + return tuName + let tutNameSuggestions = return $ mkOptionList [Option tno tn tno | etn <- tutNames, let tn = E.unValue etn, let tno = CI.original tn] + return (cid, Set.toAscList typeSet, tutNameSuggestions) -- Set in order to remove duplicates and sort ascending at once + currentRoute <- fromMaybe (error "postCAddUserR called from 404-handler") <$> getCurrentRoute confirmedActs :: Set CourseRegisterActionData <- fmap Set.fromList . throwExceptT . mapMM encodedSecretBoxOpen . lookupPostParams $ toPathPiece PostCourseUserAddConfirmAction - $logDebugS "CAddUserR confirmedActs" . tshow $ Set.map Aeson.encode confirmedActs + -- $logDebugS "CAddUserR confirmedActs" . tshow $ Set.map Aeson.encode confirmedActs unless (Set.null confirmedActs) $ do -- TODO: check that all acts are member of availableActs let users = Map.fromList . fmap (\act -> (crActIdent act, Just . view _1 $ crActUser act)) $ Set.toList confirmedActs tutActs = Set.filter (is _CourseRegisterActionAddTutorialMemberData) confirmedActs - actTutorial = crActTutorial <$> Set.lookupMin tutActs -- tutorial ident must be the same for every added member! + actTutorial = crActTutorial <$> Set.lookupMin tutActs -- tutorial ident must be the same for every added member! registeredUsers <- registerUsers cid users - forM_ actTutorial $ \tutName -> do - tutId <- upsertNewTutorial cid tutName - registerTutorialMembers tutId registeredUsers - - if - | Just tutName <- actTutorial - , Set.size tutActs == Set.size confirmedActs - -> redirect $ CTutorialR tid ssh csh tutName TUsersR - | otherwise - -> redirect $ CourseR tid ssh csh CUsersR - - ((usersToAdd :: FormResult AddUserRequest, formWgt), formEncoding) <- runFormPost . renderWForm FormStandard $ do + whenIsJust actTutorial $ \(tutName,tutType,tutDay) -> do + whenIsJust (tutName <|> fmap (tutorialDefaultName tutType) tutDay) $ \tName -> do + tutId <- upsertNewTutorial cid tName tutType tutDay + registerTutorialMembers tutId registeredUsers + -- when (Set.size tutActs == Set.size confirmedActs) $ -- not sure how this condition might be false at this point + redirect $ CTutorialR tid ssh csh tName TUsersR + redirect $ CourseR tid ssh csh CUsersR + + ((usersToAdd :: FormResult AddUserRequest, formWgt), formEncoding) <- runFormPost . renderWForm FormStandard $ do + let tutTypesMsg = [(SomeMessage tt,tt) | tt <- tutTypes] + tutDefType = ttyp >>= (\ty -> if ty `elem` tutTypes then Just ty else Nothing) auReqUsers <- wreq (textField & cfAnySeparatedSet) (fslI MsgCourseParticipantsRegisterUsersField & setTooltip MsgCourseParticipantsRegisterUsersFieldTip) mempty auReqTutorial <- optionalActionW - ( areq (textField & cfCI) (fslI MsgCourseParticipantsRegisterTutorialField & setTooltip MsgCourseParticipantsRegisterTutorialFieldTip) (Just tut) ) + ( (,,) + <$> aopt (textField & cfStrip & cfCI & addDatalist tutNameSuggestions) + (fslI MsgCourseParticipantsRegisterTutorialField & setTooltip MsgCourseParticipantsRegisterTutorialFieldTip) + (Just $ maybeLeft tdesc) + <*> aopt (selectFieldList tutTypesMsg) + (fslI MsgTableTutorialType) + (Just tutDefType) + <*> aopt dayField + (fslI MsgTableTutorialFirstDay & setTooltip MsgCourseParticipantsRegisterTutorialFirstDayTip) + (Just $ maybeRight tdesc) + ) ( fslI MsgCourseParticipantsRegisterTutorialOption ) ( Just True ) return $ AddUserRequest <$> auReqUsers <*> auReqTutorial @@ -261,32 +324,59 @@ registerUser cid (_avsIdent, Just uid) = exceptT return return $ do return $ mempty { aurRegisterSuccess = Set.singleton uid } -upsertNewTutorial :: CourseId -> TutorialIdent -> Handler TutorialId -upsertNewTutorial cid tutorialName = do +upsertNewTutorial :: CourseId -> TutorialName -> Maybe TutorialType -> Maybe Day -> Handler TutorialId +upsertNewTutorial cid newTutorialName newTutorialType newFirstDay = runDB $ do now <- liftIO getCurrentTime - runDB $ do - Entity tutId _ <- upsert - Tutorial - { tutorialCourse = cid - , tutorialType = CI.mk "Schulung" - , tutorialCapacity = Nothing - , tutorialRoom = Nothing - , tutorialRoomHidden = False - , tutorialTime = Occurrences mempty mempty - , tutorialRegGroup = Nothing -- TODO: remove - , tutorialRegisterFrom = Nothing - , tutorialRegisterTo = Nothing - , tutorialDeregisterUntil = Nothing - , tutorialLastChanged = now - , tutorialTutorControlled = False - , .. - } - [ TutorialName =. tutorialName - , TutorialType =. CI.mk "Schulung" - , TutorialLastChanged =. now - ] - audit $ TransactionTutorialEdit tutId - return tutId + existingTut <- getBy $ UniqueTutorial cid newTutorialName + templateEnt <- selectFirst [TutorialType <-. tutorialTemplateNames newTutorialType] [Desc TutorialType, Asc TutorialName] + case (existingTut, newFirstDay, templateEnt) of + (Just Entity{entityKey=tid},_,_) -> return tid -- no need to update, we ignore the anchor day + (Nothing, Just moveDay, Just Entity{entityVal=Tutorial{..}}) -> do + Course{..} <- get404 cid + term <- get404 courseTerm + let oldFirstDay = fromMaybe moveDay $ tutorialFirstDay <|> fst (occurrencesBounds term tutorialTime) + newTime = normalizeOccurrences $ occurrencesAddBusinessDays term (oldFirstDay, moveDay) tutorialTime + dayDiff = maybe 0 (diffDays moveDay) tutorialFirstDay + mvTime = fmap $ addLocalDays dayDiff + newType0 = CI.map (snd . Text.breakOnEnd (CI.original tutorialTypeSeparator)) tutorialType + newType = if newType0 `elem` tutorialTemplateNames Nothing + then fromMaybe defaultTutorialType newTutorialType + else newType0 + Entity tutId _ <- upsert + Tutorial + { tutorialName = newTutorialName + , tutorialCourse = cid + , tutorialType = newType + , tutorialFirstDay = newFirstDay + , tutorialTime = newTime + , tutorialRegisterFrom = mvTime tutorialRegisterFrom + , tutorialRegisterTo = mvTime tutorialRegisterTo + , tutorialDeregisterUntil = mvTime tutorialDeregisterUntil + , tutorialLastChanged = now + , .. + } [] -- update cannot happen due to previous case + audit $ TransactionTutorialEdit tutId + return tutId + _ -> do + Entity tutId _ <- upsert + Tutorial + { tutorialName = newTutorialName + , tutorialCourse = cid + , tutorialType = fromMaybe defaultTutorialType newTutorialType + , tutorialCapacity = Nothing + , tutorialRoom = Nothing + , tutorialRoomHidden = False + , tutorialTime = Occurrences mempty mempty + , tutorialRegGroup = Nothing + , tutorialRegisterFrom = Nothing + , tutorialRegisterTo = Nothing + , tutorialDeregisterUntil = Nothing + , tutorialLastChanged = now + , tutorialTutorControlled = False + , tutorialFirstDay = Nothing + } [] -- update cannot happen due to previous cases + audit $ TransactionTutorialEdit tutId + return tutId registerTutorialMembers :: TutorialId -> Set UserId -> Handler () registerTutorialMembers tutId (Set.toList -> users) = runDB $ do diff --git a/src/Handler/Course/Show.hs b/src/Handler/Course/Show.hs index ee3807fc3..78ddeecd5 100644 --- a/src/Handler/Course/Show.hs +++ b/src/Handler/Course/Show.hs @@ -29,7 +29,7 @@ import Handler.Exam.List (mkExamTable) getCShowR :: TermId -> SchoolId -> CourseShorthand -> Handler Html getCShowR tid ssh csh = do - mbAid <- maybeAuthId + mbAid <- maybeAuthId now <- liftIO getCurrentTime (cid,course,courseVisible,schoolName,participants,registration,lecturers,assistants,administrators,correctors,tutors,news,events,submissionGroup,_mayReRegister,(mayViewSheets, mayViewAnySheet), (mayViewMaterials, mayViewAnyMaterial),courseQualifications) <- runDB . maybeT notFound $ do [(E.Entity cid course, E.Value courseVisible, E.Value schoolName, E.Value participants, fmap entityVal -> registration)] @@ -145,7 +145,8 @@ getCShowR tid ssh csh = do } | otherwise -> return . modal $(widgetFile "course/login-to-register") . Left . SomeRoute $ AuthR LoginR - registrationOpen <- hasWriteAccessTo $ CourseR tid ssh csh CRegisterR + registrationOpen <- hasWriteAccessTo $ CourseR tid ssh csh CRegisterR + mayMassRegister <- hasWriteAccessTo $ CourseR tid ssh csh CAddUserR MsgRenderer mr <- getMsgRenderer @@ -164,9 +165,10 @@ getCShowR tid ssh csh = do dbtRowKey = (E.^. TutorialId) dbtProj = over (_dbrOutput . _2) E.unValue <$> dbtProjId dbtColonnade = dbColonnade $ mconcat - [ sortable (Just "type") (i18nCell MsgTableTutorialType) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> textCell $ CI.original tutorialType - , sortable (Just "name") (i18nCell MsgTableTutorialName) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> indicatorCell <> anchorCell (CTutorialR tid ssh csh tutorialName TUsersR) [whamlet|#{tutorialName}|] - , sortable (Just "tutors") (i18nCell MsgTableTutorialTutors) $ \(view $ resultTutorial . _entityKey -> tutid) -> sqlCell $ do + [ sortable (Just "type") (i18nCell MsgTableTutorialType) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> textCell $ CI.original tutorialType + , sortable (Just "first-day") (i18nCell MsgTableTutorialFirstDay) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> cellMaybe dayCell tutorialFirstDay + , sortable (Just "name") (i18nCell MsgTableTutorialName) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> indicatorCell <> anchorCell (CTutorialR tid ssh csh tutorialName TUsersR) [whamlet|#{tutorialName}|] + , sortable (Just "tutors") (i18nCell MsgTableTutorialTutors) $ \(view $ resultTutorial . _entityKey -> tutid) -> sqlCell $ do tutTutors <- fmap (map $(unValueN 3)) . E.select . E.from $ \(tutor `E.InnerJoin` user) -> do E.on $ tutor E.^. TutorUser E.==. user E.^. UserId E.where_ $ tutor E.^. TutorTutorial E.==. E.val tutid @@ -194,25 +196,30 @@ getCShowR tid ssh csh = do E.where_ $ participant E.^. TutorialParticipantTutorial E.==. E.val tutid in return $ E.val tutorialCapacity' E.-. numParticipants return . toWidget $ tshow freeCapacity - , sortable Nothing (mempty & cellAttrs <>~ pure ("uw-hide-columns--hider-label", mr MsgTableActionsHead)) $ \(view resultTutorial -> Entity tutId Tutorial{..}) -> sqlCell $ do - mayRegister <- (== Authorized) <$> evalAccessDB (CTutorialR tid ssh csh tutorialName TRegisterR) True - isRegistered <- case mbAid of - Nothing -> return False - Just uid -> existsBy $ UniqueTutorialParticipant tutId uid - if - | mayRegister -> do - (tutRegisterForm, tutRegisterEnctype) <- liftHandler . generateFormPost . buttonForm' $ bool [BtnRegister] [BtnDeregister] isRegistered - return $ wrapForm tutRegisterForm def - { formAction = Just . SomeRoute $ CTutorialR tid ssh csh tutorialName TRegisterR - , formEncoding = tutRegisterEnctype - , formSubmit = FormNoSubmit - } - | isRegistered -> return [whamlet|_{MsgTutorialRegistered}|] - | otherwise -> return mempty + , guardMonoid (not mayMassRegister || isJust registration) $ + sortable Nothing (mempty & cellAttrs <>~ pure ("uw-hide-columns--hider-label", mr MsgTableActionsHead)) $ \(view resultTutorial -> Entity tutId Tutorial{..}) -> sqlCell $ do + mayRegister <- (== Authorized) <$> evalAccessDB (CTutorialR tid ssh csh tutorialName TRegisterR) True + isRegistered <- case mbAid of + Nothing -> return False + Just uid -> existsBy $ UniqueTutorialParticipant tutId uid + if + | mayRegister -> do + (tutRegisterForm, tutRegisterEnctype) <- liftHandler . generateFormPost . buttonForm' $ bool [BtnRegister] [BtnDeregister] isRegistered + return $ wrapForm tutRegisterForm def + { formAction = Just . SomeRoute $ CTutorialR tid ssh csh tutorialName TRegisterR + , formEncoding = tutRegisterEnctype + , formSubmit = FormNoSubmit + } + | isRegistered -> return [whamlet|_{MsgTutorialRegistered}|] + | otherwise -> return mempty + , guardMonoid mayMassRegister $ + sortable Nothing (mempty & cellAttrs <>~ pure ("uw-hide-columns--hider-label", mr MsgTableActionsHead)) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> + cell $ linkButton mempty (msg2widget MsgMassRegister) [BCIsButton, BCPrimary] (SomeRoute $ CTutorialR tid ssh csh tutorialName TAddUserR) ] dbtSorting = Map.fromList [ ("type", SortColumn $ \tutorial -> tutorial E.^. TutorialType ) , ("name", SortColumn $ \tutorial -> tutorial E.^. TutorialName ) + , ("first-day", SortColumnNullsInv $ \tutorial -> tutorial E.^. TutorialFirstDay ) , ("room", SortColumn $ \tutorial -> tutorial E.^. TutorialRoom ) , ("register-from", SortColumn $ \tutorial -> tutorial E.^. TutorialRegisterFrom ) , ("register-to", SortColumn $ \tutorial -> tutorial E.^. TutorialRegisterTo ) @@ -235,7 +242,7 @@ getCShowR tid ssh csh = do dbtExtraReps = [] tutorialDBTableValidator = def - & defaultSorting [SortAscBy "type", SortDescBy "name"] + & defaultSorting [SortAscBy "type", SortDescBy "first-day", SortAscBy "name"] (Any hasTutorials, tutorialTable) <- runDB $ dbTable tutorialDBTableValidator tutorialDBTable (Any hasExams, examTable) <- runDB . mkExamTable $ Entity cid course diff --git a/src/Handler/LMS.hs b/src/Handler/LMS.hs index 0a50be36f..a07d24e9d 100644 --- a/src/Handler/LMS.hs +++ b/src/Handler/LMS.hs @@ -696,18 +696,23 @@ postLmsR sid qsh = do (action, selectedUsers) | isRenewPinAct action || isNotifyAct action -> do numExaminees <- runDBJobs $ do - okUsers <- selectList [LmsUserUser <-. Set.toList selectedUsers, LmsUserQualification ==. qid] [] + okUsers <- selectList [ LmsUserQualification ==. qid -- matching qualification + , LmsUserEnded ==. Nothing -- not yet deleted + , LmsUserStatus ==. Nothing -- not yet decided + , LmsUserUser <-. Set.toList selectedUsers -- selected + ] [] forM_ okUsers $ \(Entity lid LmsUser {lmsUserUser = uid, lmsUserQualification = qid'}) -> do when (isRenewPinAct action) $ do newPin <- liftIO randomLMSpw update lid [LmsUserPin =. newPin, LmsUserDatePin =. now, LmsUserResetPin =. True] when (isNotifyAct action) $ - queueDBJob $ JobSendNotification { jRecipient = uid, jNotification = NotificationQualificationRenewal qid' } + queueDBJob $ JobUserNotification { jRecipient = uid, jNotification = NotificationQualificationRenewal qid' False } return $ length okUsers let numSelected = length selectedUsers diffSelected = numSelected - numExaminees - when (isRenewPinAct action) $ addMessageI Success $ MsgLmsPinRenewal numExaminees - when (isNotifyAct action) $ addMessageI Success $ MsgLmsNotificationSend numExaminees + mstat = bool Success Warning $ diffSelected /= 0 + when (isRenewPinAct action) $ addMessageI mstat $ MsgLmsPinRenewal numExaminees + when (isNotifyAct action) $ addMessageI mstat $ MsgLmsNotificationSend numExaminees when (diffSelected /= 0) $ addMessageI Warning $ MsgLmsActionFailed diffSelected reloadKeepGetParams $ LmsR sid qsh _ -> addMessageI Error MsgUnauthorized -- should not happen @@ -772,5 +777,4 @@ viewLmsUserR msid mqsh uuid = do let heading = [whamlet|_{MsgMenuLmsUser} ^{userWidget user}|] siteLayout heading $ do setTitle $ toHtml userDisplayName - $(widgetFile "lms-user") - -- $(i18nWidgetFile "lms-user") + $(widgetFile "lms-user") diff --git a/src/Handler/PrintCenter.hs b/src/Handler/PrintCenter.hs index f12f5b9af..90889c63d 100644 --- a/src/Handler/PrintCenter.hs +++ b/src/Handler/PrintCenter.hs @@ -40,26 +40,29 @@ single = uncurry Map.singleton data LRQF = LRQF - { lrqfLetter :: Text - , lrqfUser :: Either UserEmail UserId - , lrqfSuper :: Maybe (Either UserEmail UserId) - , lrqfQuali :: Entity Qualification - , lrqfIdent :: LmsIdent - , lrqfPin :: Text - , lrqfExpiry :: Maybe Day + { lrqfLetter :: Text + , lrqfUser :: Either UserEmail UserId + , lrqfSuper :: Maybe (Either UserEmail UserId) + , lrqfQuali :: Entity Qualification + , lrqfIdent :: LmsIdent + , lrqfPin :: Text + , lrqfExpiry :: Maybe Day + , lrqfReminder :: Bool } deriving (Eq, Generic) makeRenewalForm :: Maybe LRQF -> Form LRQF makeRenewalForm tmpl = identifyForm FIDLmsLetter . validateForm validateLetterRenewQualificationF $ \html -> do -- now_day <- utctDay <$> liftIO getCurrentTime flip (renderAForm FormStandard) html $ LRQF - <$> areq textField (fslI MsgPrintLetterType) (lrqfLetter <$> tmpl) - <*> areq (userField False Nothing) (fslI MsgLmsUser) (lrqfUser <$> tmpl) - <*> aopt (userField False Nothing) (fslI MsgTableSupervisor) (lrqfSuper <$> tmpl) - <*> areq qualificationFieldEnt (fslI MsgQualificationName) (lrqfQuali <$> tmpl) - <*> areq lmsField (fslI MsgTableLmsIdent) (lrqfIdent <$> tmpl) - <*> areq textField (fslI MsgTableLmsPin) (lrqfPin <$> tmpl) - <*> aopt dayField (fslI MsgLmsQualificationValidUntil) (lrqfExpiry <$> tmpl) + <$> areq textField (fslI MsgPrintLetterType) (lrqfLetter <$> tmpl) + <*> areq (userField False Nothing) (fslI MsgLmsUser) (lrqfUser <$> tmpl) + <*> aopt (userField False Nothing) (fslI MsgTableSupervisor) (lrqfSuper <$> tmpl) + <*> areq qualificationFieldEnt (fslI MsgQualificationName) (lrqfQuali <$> tmpl) + <*> areq lmsField (fslI MsgTableLmsIdent) (lrqfIdent <$> tmpl) + <*> areq textField (fslI MsgTableLmsPin) (lrqfPin <$> tmpl) + <*> aopt dayField (fslI MsgLmsQualificationValidUntil) (lrqfExpiry <$> tmpl) + <*> areq (boolField . Just $ SomeMessage MsgBoolIrrelevant) + (fslI MsgLmsRenewalReminder) (lrqfReminder <$> tmpl) where lmsField = convertField LmsIdent getLmsIdent textField @@ -86,6 +89,7 @@ lrqf2letter LRQF{..} , qualShort = lrqfQuali ^. _qualificationShorthand . _CI , qualSchool = lrqfQuali ^. _qualificationSchool , qualDuration = lrqfQuali ^. _qualificationValidDuration + , isReminder = lrqfReminder } return (fromMaybe usr rcvr, SomeLetter letter) | lrqfLetter == "e" || lrqfLetter == "E" = do @@ -94,17 +98,17 @@ lrqf2letter LRQF{..} usrShrt <- encrypt $ entityKey usr usrUuid <- encrypt $ entityKey usr urender <- liftHandler getUrlRender - let letter = LetterExpireQualificationF - { leqfHolderCFN = usrShrt - , leqfHolderID = usr ^. _entityKey - , leqfHolderDN = usr ^. _userDisplayName - , leqfHolderSN = usr ^. _userSurname - , leqfExpiry = lrqfExpiry - , leqfId = lrqfQuali ^. _entityKey - , leqfName = lrqfQuali ^. _qualificationName . _CI - , leqfShort = lrqfQuali ^. _qualificationShorthand . _CI - , leqfSchool = lrqfQuali ^. _qualificationSchool - , leqfUrl = pure . urender $ ForProfileDataR usrUuid + let letter = LetterExpireQualification + { leqHolderCFN = usrShrt + , leqHolderID = usr ^. _entityKey + , leqHolderDN = usr ^. _userDisplayName + , leqHolderSN = usr ^. _userSurname + , leqExpiry = lrqfExpiry + , leqId = lrqfQuali ^. _entityKey + , leqName = lrqfQuali ^. _qualificationName . _CI + , leqShort = lrqfQuali ^. _qualificationShorthand . _CI + , leqSchool = lrqfQuali ^. _qualificationSchool + , leqUrl = pure . urender $ ForProfileDataR usrUuid } return (fromMaybe usr rcvr, SomeLetter letter) | otherwise = error "Unknown Letter Type encountered. Use 'e' or 'r' only." @@ -114,17 +118,16 @@ lrqf2letter LRQF{..} getUser (Left mail) = getBy404 $ UniqueEmail mail -data PJTableAction = PJActAcknowledge +data PJTableAction = PJActAcknowledge | PJActReprint deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic) - instance Universe PJTableAction instance Finite PJTableAction nullaryPathPiece ''PJTableAction $ camelToPathPiece' 2 embedRenderMessage ''UniWorX ''PJTableAction id -- Not yet needed, since there is no additional data for now: -data PJTableActionData = PJActAcknowledgeData +data PJTableActionData = PJActAcknowledgeData | PJActReprintData deriving (Eq, Ord, Read, Show, Generic) type PJTableExpr = ( E.SqlExpr (Entity PrintJob) @@ -259,6 +262,7 @@ mkPJTable = do = let acts :: Map PJTableAction (AForm Handler PJTableActionData) acts = mconcat [ singletonMap PJActAcknowledge $ pure PJActAcknowledgeData + , singletonMap PJActReprint $ pure PJActReprintData ] in renderAForm FormStandard $ (, mempty) . First . Just @@ -283,11 +287,19 @@ postPrintCenterR = do (pjRes, pjTable) <- runDB mkPJTable formResult pjRes $ \case - (PJActAcknowledgeData, Set.toList -> pjIds) -> do - now <- liftIO getCurrentTime - num <- runDB $ updateWhereCount [PrintJobAcknowledged ==. Nothing, PrintJobId <-. pjIds] [PrintJobAcknowledged =. Just now] - addMessageI Success $ MsgPrintJobAcknowledge num - reloadKeepGetParams PrintCenterR + (PJActAcknowledgeData, Set.toList -> pjIds) -> do + now <- liftIO getCurrentTime + num <- runDB $ updateWhereCount [PrintJobAcknowledged ==. Nothing, PrintJobId <-. pjIds] [PrintJobAcknowledged =. Just now] + addMessageI Success $ MsgPrintJobAcknowledge num + reloadKeepGetParams PrintCenterR + (PJActReprintData, Set.toList -> pjIds) -> do + let countOk = either (const $ Sum 0) (const $ Sum 1) + oks <- runDB $ forM pjIds $ fmap countOk . reprintPDF + let nr_oks = getSum $ mconcat oks + nr_tot = length pjIds + mstat = bool Warning Success $ nr_oks == nr_tot + addMessageI mstat $ MsgPrintJobReprint nr_oks nr_tot + reloadKeepGetParams PrintCenterR siteLayoutMsg MsgMenuApc $ do setTitleI MsgMenuApc @@ -310,6 +322,7 @@ postPrintSendR = do , lrqfIdent = LmsIdent "stuvwxyz" , lrqfPin = "76543210" , lrqfExpiry = Just $ succ nowaday + , lrqfReminder = False } def_lrqf = mkLetter <$> mbQual diff --git a/src/Handler/Profile.hs b/src/Handler/Profile.hs index 71d55abca..bd1762c95 100644 --- a/src/Handler/Profile.hs +++ b/src/Handler/Profile.hs @@ -247,10 +247,11 @@ notificationForm template = wFormToAForm $ do NTExamOfficeExamResults -> Just $ NTKFunctionary SchoolExamOffice NTExamOfficeExamResultsChanged -> Just $ NTKFunctionary SchoolExamOffice NTCourseRegistered -> Just NTKAll - NTQualification -> Just NTKAll + NTQualificationExpiry -> Just NTKAll + NTQualificationReminder -> Just NTKAll -- _other -> Nothing - forcedTriggers = [NTUserRightsUpdate, NTUserAuthModeUpdate] + forcedTriggers = [NTUserRightsUpdate, NTUserAuthModeUpdate, NTQualificationExpiry] aFormToWForm $ NotificationSettings <$> sectionedFuncForm ntSection nsForm (fslI MsgNotificationSettings) False diff --git a/src/Handler/Qualification.hs b/src/Handler/Qualification.hs index 411bb89f8..0615c8fb8 100644 --- a/src/Handler/Qualification.hs +++ b/src/Handler/Qualification.hs @@ -97,11 +97,14 @@ mkQualificationAllTable isAdmin = do maybeCell (qualificationDescription quali) markupCellLargeModal , sortable Nothing (i18nCell MsgQualificationValidDuration & cellTooltip MsgTableDiffDaysTooltip) $ foldMap (textCell . formatCalendarDiffDays . fromMonths) . view (resultAllQualification . _qualificationValidDuration) - , sortable Nothing (i18nCell MsgQualificationRefreshWithin & cellTooltip MsgTableDiffDaysTooltip) $ - foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshWithin) - -- , sortable Nothing (i18nCell MsgQualificationRefreshWithin) $ foldMap textCell . view (resultAllQualification . _qualificationRefreshWithin . to formatCalendarDiffDays) -- does not work, since there is a maybe in between + , sortable Nothing (i18nCell MsgQualificationRefreshWithin & cellTooltip MsgQualificationRefreshWithinTooltip) $ + foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshWithin) + , sortable Nothing (i18nCell MsgQualificationRefreshReminder & cellTooltip MsgQualificationRefreshReminderTooltip) $ + foldMap (textCell . formatCalendarDiffDays ) . view (resultAllQualification . _qualificationRefreshReminder) , sortable (Just "qelearning") (i18nCell MsgTableLmsElearning & cellTooltip MsgQualificationElearningStart) $ tickmarkCell . view (resultAllQualification . _qualificationElearningStart) + , sortable (Just "noteexpiry") (i18nCell MsgQualificationExpiryNotification & cellTooltip MsgQualificationExpiryNotificationTooltip) + $ tickmarkCell . view (resultAllQualification . _qualificationExpiryNotification) , sortable Nothing (i18nCell MsgTableQualificationIsAvsLicence & cellTooltip MsgTableQualificationIsAvsLicenceTooltip) $ \(view (resultAllQualification . _qualificationAvsLicence) -> licence) -> maybeCell licence $ textCell . T.singleton . licence2char , sortable Nothing (i18nCell MsgTableQualificationSapExport & cellTooltip MsgTableQualificationSapExportTooltip) @@ -116,6 +119,7 @@ mkQualificationAllTable isAdmin = do , singletonMap "qshort" $ SortColumn (E.^. QualificationShorthand) , singletonMap "qname" $ SortColumn (E.^. QualificationName) , singletonMap "qelearning" $ SortColumn (E.^. QualificationElearningStart) + , singletonMap "noteexpiry" $ SortColumn (E.^. QualificationExpiryNotification) ] dbtFilter = mconcat [ @@ -432,6 +436,10 @@ mkQualificationTable isAdmin (Entity qid quali) acts cols psValidator = do E.&&. quser E.^. QualificationUserValidUntil E.>=. E.val nowaday | otherwise -> E.true ) + , single ("tobe-notified", FilterColumn $ \(queryQualUser -> quser) criterion -> + if | Just True <- getLast criterion -> quser `quserToNotify` now + | otherwise -> E.true + ) ] dbtFilterUI mPrev = mconcat [ fltrUserNameEmailHdrUI MsgLmsUser mPrev @@ -442,6 +450,7 @@ mkQualificationTable isAdmin (Entity qid quali) acts cols psValidator = do , prismAForm (singletonFilter "validity" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterLmsValid) , if isNothing mbRenewal then mempty else prismAForm (singletonFilter "renewal-due" . maybePrism _PathPiece) mPrev $ aopt checkBoxField (fslI MsgFilterLmsRenewal) + , prismAForm (singletonFilter "tobe-notified" . maybePrism _PathPiece) mPrev $ aopt checkBoxField (fslI MsgFilterLmsNotificationDue) ] dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout } dbtCsvEncode = Just DBTCsvEncode diff --git a/src/Handler/Tutorial/Edit.hs b/src/Handler/Tutorial/Edit.hs index 3c58cf3f1..65d616e0a 100644 --- a/src/Handler/Tutorial/Edit.hs +++ b/src/Handler/Tutorial/Edit.hs @@ -25,15 +25,14 @@ getTEditR, postTEditR :: TermId -> SchoolId -> CourseShorthand -> TutorialName - getTEditR = postTEditR postTEditR tid ssh csh tutn = do (cid, tutid, template) <- runDB $ do - (cid, Entity tutid Tutorial{..}) <- fetchCourseIdTutorial tid ssh csh tutn - + (cid, Entity tutid Tutorial{..}) <- fetchCourseIdTutorial tid ssh csh tutn tutorIds <- fmap (map E.unValue) . E.select . E.from $ \tutor -> do E.where_ $ tutor E.^. TutorTutorial E.==. E.val tutid return $ tutor E.^. TutorUser tutorInvites <- sourceInvitationsF @Tutor tutid - let + let template = TutorialForm { tfName = tutorialName , tfType = tutorialType @@ -56,6 +55,7 @@ postTEditR tid ssh csh tutn = do formResult newTutResult $ \TutorialForm{..} -> do insertRes <- runDBJobs $ do + term <- fetchTermByCID cid now <- liftIO getCurrentTime insertRes <- myReplaceUnique tutid Tutorial { tutorialName = tfName @@ -71,6 +71,7 @@ postTEditR tid ssh csh tutn = do , tutorialDeregisterUntil = tfDeregisterUntil , tutorialLastChanged = now , tutorialTutorControlled = tfTutorControlled + , tutorialFirstDay = fst $ occurrencesBounds term tfTime } when (is _Nothing insertRes) $ do audit $ TransactionTutorialEdit tutid diff --git a/src/Handler/Tutorial/List.hs b/src/Handler/Tutorial/List.hs index fa24a5966..3f0c6a48d 100644 --- a/src/Handler/Tutorial/List.hs +++ b/src/Handler/Tutorial/List.hs @@ -44,9 +44,10 @@ getCTutorialListR tid ssh csh = do dbtRowKey = (E.^. TutorialId) dbtProj = over (_dbrOutput . _2) E.unValue . over (_dbrOutput . _3) E.unValue <$> dbtProjId dbtColonnade = dbColonnade $ mconcat - [ sortable (Just "type") (i18nCell MsgTableTutorialType) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> textCell $ CI.original tutorialType - , sortable (Just "name") (i18nCell MsgTableTutorialName) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> anchorCell (CTutorialR tid ssh csh tutorialName TUsersR) [whamlet|#{tutorialName}|] - , sortable (Just "tutors") (i18nCell MsgTableTutorialTutors) $ \(view $ resultTutorial . _entityKey -> tutid) -> sqlCell $ do + [ sortable (Just "type") (i18nCell MsgTableTutorialType) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> textCell $ CI.original tutorialType + , sortable (Just "first-day") (i18nCell MsgTableTutorialFirstDay) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> cellMaybe dayCell tutorialFirstDay + , sortable (Just "name") (i18nCell MsgTableTutorialName) $ \(view $ resultTutorial . _entityVal -> Tutorial{..}) -> anchorCell (CTutorialR tid ssh csh tutorialName TUsersR) [whamlet|#{tutorialName}|] + , sortable (Just "tutors") (i18nCell MsgTableTutorialTutors) $ \(view $ resultTutorial . _entityKey -> tutid) -> sqlCell $ do tutors <- fmap (map $(unValueN 3)) . E.select . E.from $ \(tutor `E.InnerJoin` user) -> do E.on $ tutor E.^. TutorUser E.==. user E.^. UserId E.where_ $ tutor E.^. TutorTutorial E.==. E.val tutid @@ -73,8 +74,9 @@ getCTutorialListR tid ssh csh = do linkButton mempty [whamlet|_{MsgTutorialDelete}|] [BCIsButton, BCDanger] . SomeRoute $ CTutorialR tid ssh csh tutorialName TDeleteR ] dbtSorting = Map.fromList - [ ("type", SortColumn $ \tutorial -> tutorial E.^. TutorialType ) - , ("name", SortColumn $ \tutorial -> tutorial E.^. TutorialName ) + [ ("type" , SortColumn $ \tutorial -> tutorial E.^. TutorialType ) + , ("name" , SortColumn $ \tutorial -> tutorial E.^. TutorialName ) + , ("first-day", SortColumnNullsInv $ \tutorial -> tutorial E.^. TutorialFirstDay ) , ( "tutors" , SortColumn $ \tutorial -> E.subSelectMaybe . E.from $ \(tutor `E.InnerJoin` user) -> do E.on $ tutor E.^. TutorUser E.==. user E.^. UserId @@ -89,9 +91,9 @@ getCTutorialListR tid ssh csh = do , ("capacity", SortColumn $ \tutorial -> tutorial E.^. TutorialCapacity ) , ("room", SortColumn $ \tutorial -> tutorial E.^. TutorialRoom ) , ("register-group", SortColumn $ \tutorial -> tutorial E.^. TutorialRegGroup ) - , ("register-from", SortColumn $ \tutorial -> tutorial E.^. TutorialRegisterFrom ) - , ("register-to", SortColumn $ \tutorial -> tutorial E.^. TutorialRegisterTo ) - , ("deregister-until", SortColumn $ \tutorial -> tutorial E.^. TutorialDeregisterUntil ) + , ("register-from" , SortColumnNullsInv $ \tutorial -> tutorial E.^. TutorialRegisterFrom ) + , ("register-to" , SortColumnNullsInv $ \tutorial -> tutorial E.^. TutorialRegisterTo ) + , ("deregister-until" , SortColumnNullsInv $ \tutorial -> tutorial E.^. TutorialDeregisterUntil ) ] dbtFilter = Map.empty dbtFilterUI = const mempty @@ -104,7 +106,7 @@ getCTutorialListR tid ssh csh = do dbtExtraReps = [] tutorialDBTableValidator = def - & defaultSorting [SortAscBy "type", SortAscBy "name"] + & defaultSorting [SortAscBy "type", SortDescBy "first-day", SortAscBy "name"] ((), tutorialTable) <- runDB $ dbTable tutorialDBTableValidator tutorialDBTable siteLayoutMsg (prependCourseTitle tid ssh csh MsgTutorialsHeading) $ do diff --git a/src/Handler/Tutorial/New.hs b/src/Handler/Tutorial/New.hs index 8f81c5dcb..4fa98b0d6 100644 --- a/src/Handler/Tutorial/New.hs +++ b/src/Handler/Tutorial/New.hs @@ -20,13 +20,14 @@ import Handler.Tutorial.TutorInvite getCTutorialNewR, postCTutorialNewR :: TermId -> SchoolId -> CourseShorthand -> Handler Html getCTutorialNewR = postCTutorialNewR postCTutorialNewR tid ssh csh = do - cid <- runDB . getKeyBy404 $ TermSchoolCourseShort tid ssh csh + Entity{entityKey=cid, entityVal=course} <- runDB . getBy404 $ TermSchoolCourseShort tid ssh csh -- TODO: use getKeyBy404 if was optimized to no longer retrieve the full entity from the DB anyway ((newTutResult, newTutWidget), newTutEnctype) <- runFormPost $ tutorialForm cid Nothing formResult newTutResult $ \TutorialForm{..} -> do - insertRes <- runDBJobs $ do + insertRes <- runDBJobs $ do now <- liftIO getCurrentTime + term <- get404 $ course ^. _courseTerm insertRes <- insertUnique Tutorial { tutorialName = tfName , tutorialCourse = cid @@ -41,6 +42,7 @@ postCTutorialNewR tid ssh csh = do , tutorialDeregisterUntil = tfDeregisterUntil , tutorialLastChanged = now , tutorialTutorControlled = tfTutorControlled + , tutorialFirstDay = fst $ occurrencesBounds term tfTime } whenIsJust insertRes $ \tutid -> do audit $ TransactionTutorialEdit tutid diff --git a/src/Handler/Tutorial/Users.hs b/src/Handler/Tutorial/Users.hs index 79eca5079..7b76714de 100644 --- a/src/Handler/Tutorial/Users.hs +++ b/src/Handler/Tutorial/Users.hs @@ -1,4 +1,4 @@ --- SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vaupel +-- SPDX-FileCopyrightText: 2022-23 Gregor Kleen ,Sarah Vaupel ,Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later @@ -45,8 +45,6 @@ embedRenderMessage ''UniWorX ''TutorialUserAction id data TutorialUserActionData = TutorialUserPrintQualificationData - { tuQualification :: QualificationId - } | TutorialUserRenewQualificationData { tuQualification :: QualificationId } | TutorialUserGrantQualificationData @@ -100,11 +98,7 @@ postTUsersR tid ssh csh tutn = do acts :: Map TutorialUserAction (AForm Handler TutorialUserActionData) acts = Map.fromList $ (if null qualifications then mempty else - [ ( TutorialUserPrintQualification - , TutorialUserPrintQualificationData - <$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing - ) - , ( TutorialUserRenewQualification + [ ( TutorialUserRenewQualification , TutorialUserRenewQualificationData <$> apopt (selectField . fmap mkOptionList $ mapM qualOpt qualifications) (fslI MsgQualificationName) Nothing ) @@ -115,16 +109,16 @@ postTUsersR tid ssh csh tutn = do ) ] ) ++ - [ ( TutorialUserSendMail, pure TutorialUserSendMailData ) - , ( TutorialUserDeregister, pure TutorialUserDeregisterData ) + [ ( TutorialUserSendMail , pure TutorialUserSendMailData ) + , ( TutorialUserDeregister , pure TutorialUserDeregisterData ) + , ( TutorialUserPrintQualification, pure TutorialUserPrintQualificationData ) ] table <- makeCourseUserTable cid acts isInTut colChoices psValidator (Just csvColChoices) return (tutEnt, table, qualifications) let courseQids = Set.fromList (entityKey <$> qualifications) tcontent <- formResultMaybe participantRes $ \case - (TutorialUserPrintQualificationData{..}, selectedUsers) - | tuQualification `Set.member` courseQids -> do + (TutorialUserPrintQualificationData, selectedUsers) -> do rcvr <- requireAuth encRcvr <- encrypt $ entityKey rcvr letters <- runDB $ makeCourseCertificates tut Nothing $ toList selectedUsers diff --git a/src/Handler/Users.hs b/src/Handler/Users.hs index 888ccf2a4..ad3ab6ee1 100644 --- a/src/Handler/Users.hs +++ b/src/Handler/Users.hs @@ -353,7 +353,7 @@ postUsersR = do , dbtExtraReps = [] } - -- $logInfoS "UsersFormResult" $ tshow usersRes + -- $logInfoS "UsersFormResult" $ tshow usersRes formResult usersRes $ \case (act, usersSet) | Set.null usersSet && isNotSetSupervisor act -> diff --git a/src/Handler/Utils/Avs.hs b/src/Handler/Utils/Avs.hs index 03d059561..ce86e627d 100644 --- a/src/Handler/Utils/Avs.hs +++ b/src/Handler/Utils/Avs.hs @@ -1,4 +1,4 @@ --- SPDX-FileCopyrightText: 2022 Steffen Jost +-- SPDX-FileCopyrightText: 2022-23 Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later @@ -333,9 +333,9 @@ guessAvsUser (Text.splitAt 6 -> ("AVSID:", avsidTxt)) = ifMaybeM (readMay avsidT extractUid (Entity _ UserAvs{userAvsUser=uid}) = return $ Just uid in maybeM maybeAvsUpsert extractUid $ runDB $ getBy $ UniqueUserAvsId avsid guessAvsUser (Text.splitAt 6 -> ("AVSNO:", avsnoTxt)) = ifMaybeM (readMay avsnoTxt) Nothing $ \avsno -> - runDB (selectList [UserAvsNoPerson ==. avsno] []) >>= \case - [Entity _ UserAvs{userAvsUser=uid}] -> return $ Just uid - _ -> return Nothing + runDB (selectList [UserAvsNoPerson ==. avsno] []) <&> \case + [Entity _ UserAvs{userAvsUser=uid}] -> Just uid + _ -> Nothing guessAvsUser someid = do let maybeUpsertAvsUserByCard = maybeCatchAll . upsertAvsUserByCard case discernAvsCardPersonalNo someid of @@ -417,19 +417,19 @@ upsertAvsUserById api = do $logInfoS "AVS" $ "Creating new user with avsInternalPersonalNo " <> tshow persNo candidates <- selectKeysList [UserCompanyPersonalNumber ==. Just persNo] [] case candidates of - [uid] -> $logInfoS "AVS" "Matching user found, linking." >> insertUniqueEntity (UserAvs api uid avsPersonPersonNo now) + [uid] -> $logInfoS "AVS" "Matching user found, linking." >> insertUniqueEntity (UserAvs api uid avsPersonPersonNo now Nothing) (_:_) -> throwM $ AvsUserAmbiguous api [] -> do upsRes :: Either SomeException (Entity User) <- try $ ldapLookupAndUpsert persNo $logInfoS "AVS" $ "No matching existing user found. Attempted LDAP upsert returned: " <> tshow upsRes case upsRes of - Right Entity{entityKey=uid} -> insertUniqueEntity $ UserAvs api uid avsPersonPersonNo now -- pin/addr are updated in next step anyway + Right Entity{entityKey=uid} -> insertUniqueEntity $ UserAvs api uid avsPersonPersonNo now Nothing -- pin/addr are updated in next step anyway Left err -> do $logWarnS "AVS" $ "AVS user with avsInternalPersonalNo " <> tshow persNo <> " not found in LDAP: " <> tshow err return mbuid -- == Nothing -- user could not be created somehow (Just Entity{ entityKey = uaid }, _) -> do - update uaid [ UserAvsLastSynch =. now ] -- mark as updated early, to prevent failed users to clog the synch + update uaid [ UserAvsLastSynch =. now, UserAvsLastSynchError =. Nothing ] -- mark as updated early, to prevent failed users to clog the synch return mbuid _other -> return mbuid $logInfoS "AVS" $ "upsert prestep result: " <> tshow mbuid <> " --- " <> tshow mbapd @@ -464,7 +464,7 @@ upsertAvsUserById api = do } mbUid <- addNewUser newUsr -- triggers JobSynchroniseLdapUser, JobSendPasswordReset and NotificationUserAutoModeUpdate -- TODO: check if these are failsafe whenIsJust mbUid $ \uid -> runDB $ do - insert_ $ UserAvs avsPersonPersonID uid avsPersonPersonNo now + insert_ $ UserAvs avsPersonPersonID uid avsPersonPersonNo now Nothing forM_ avsPersonPersonCards $ -- save all cards for later comparisons whether an update occurred -- let cs :: Set AvsDataPersonCard = Set.fromList $ catMaybes [pinCard, addrCard] -- forM_ cs $ -- only save used cards for the postal address update detection diff --git a/src/Handler/Utils/DateTime.hs b/src/Handler/Utils/DateTime.hs index 80669b061..cfe920688 100644 --- a/src/Handler/Utils/DateTime.hs +++ b/src/Handler/Utils/DateTime.hs @@ -24,7 +24,7 @@ module Handler.Utils.DateTime , fromDays, fromMonths , weeksToAdd , setYear, getYear - , firstDayOfWeekOnAfter + , firstDayOfWeekOnAfter, daysOfWeekBetween , ceilingQuarterHour , formatGregorianW ) where @@ -44,6 +44,7 @@ import qualified Data.Csv as Csv import qualified Data.Char as Char +import Data.List (iterate) ------------- -- UTCTime -- @@ -283,6 +284,9 @@ dayOfWeekDiff a b = mod (fromEnum a - fromEnum b) 7 firstDayOfWeekOnAfter :: DayOfWeek -> Day -> Day firstDayOfWeekOnAfter dw d = addDays (toInteger $ dayOfWeekDiff dw $ dayOfWeek d) d +daysOfWeekBetween :: (Day, Day) -> DayOfWeek -> Set Day +daysOfWeekBetween (dstart, dend) wday = Set.fromAscList $ takeWhile (dend >=) $ iterate (addDays 7) $ firstDayOfWeekOnAfter wday dstart + addOneWeek :: UTCTime -> UTCTime addOneWeek = addWeeks 1 diff --git a/src/Handler/Utils/Invitations.hs b/src/Handler/Utils/Invitations.hs index df77997e7..c7f567fe3 100644 --- a/src/Handler/Utils/Invitations.hs +++ b/src/Handler/Utils/Invitations.hs @@ -7,9 +7,7 @@ {-# OPTIONS_GHC -fno-warn-redundant-constraints #-} module Handler.Utils.Invitations - ( -- * Procedure - -- - -- $procedure + ( -- * Procedure IsInvitableJunction(..) , Invitation' , _invitationDBData, _invitationTokenData @@ -435,7 +433,7 @@ instance InvitationR b => InvitationR (a -> b) where invitationR cfg _ = invitationR cfg --- $procedure +-- $procedure -- -- `Invitation`s encode a pending entry of some junction table between some -- record and `User` e.g. diff --git a/src/Handler/Utils/Occurrences.hs b/src/Handler/Utils/Occurrences.hs index 2551d57f3..984a4b7a2 100644 --- a/src/Handler/Utils/Occurrences.hs +++ b/src/Handler/Utils/Occurrences.hs @@ -4,12 +4,15 @@ module Handler.Utils.Occurrences ( occurrencesWidget + , occurrencesBounds + , occurrencesAddBusinessDays ) where import Import import qualified Data.Set as Set +import Utils.Holidays (isWeekend) import Utils.Occurrences import Handler.Utils.DateTime @@ -31,3 +34,46 @@ occurrencesWidget (normalizeOccurrences -> Occurrences{..}) = do exceptTime' <- formatTime SelFormatDateTime exceptTime $(widgetFile "widgets/occurrence/cell/except-no-occur") $(widgetFile "widgets/occurrence/cell") + +-- | Get bounds for an Occurrences +occurrencesBounds :: Term -> Occurrences -> (Maybe Day, Maybe Day) +occurrencesBounds Term{..} Occurrences{..} = (Set.lookupMin occDays, Set.lookupMax occDays) + where + occDays = (scdDays <> plsDays) \\ excDays -- (excDays <> termHolidays term) -- TODO: should holidays be exluded here? Probably not, as they can be added as exceptions already + + scdDays = Set.foldr getOccDays mempty occurrencesScheduled + (plsDays,excDays) = Set.foldr getExcDays mempty occurrencesExceptions + + getExcDays :: OccurrenceException -> (Set Day, Set Day) -> (Set Day, Set Day) + getExcDays ExceptNoOccur{exceptTime} (occ,exc) = (occ, Set.insert (localDay exceptTime) exc) + getExcDays ExceptOccur{exceptDay} (occ,exc) = (Set.insert exceptDay occ, exc) + + getOccDays :: OccurrenceSchedule -> Set Day -> Set Day + getOccDays ScheduleWeekly{scheduleDayOfWeek=wday} = Set.union $ daysOfWeekBetween (termLectureStart,termLectureEnd) wday + +occurrencesAddBusinessDays :: Term -> (Day,Day) -> Occurrences -> Occurrences +occurrencesAddBusinessDays Term{..} (dayOld, dayNew) Occurrences{..} = Occurrences newSchedule newExceptions + where + newSchedule = Set.map switchDayOfWeek occurrencesScheduled + dayDiff = diffDays dayNew dayOld + + offDays = Set.fromList $ termHolidays <> weekends + weekends = [d | d <- [(min termLectureStart termStart)..(max termEnd termLectureEnd)], isWeekend d] + + switchDayOfWeek :: OccurrenceSchedule -> OccurrenceSchedule + switchDayOfWeek os | 0 == dayDiff `mod` 7 = os + switchDayOfWeek os@ScheduleWeekly{scheduleDayOfWeek=wday} = os{scheduleDayOfWeek= toEnum (fromIntegral dayDiff + fromEnum wday)} + + newExceptions = snd $ Set.foldl' advanceExceptions (dayDiff,mempty) occurrencesExceptions + + -- we assume that instance Ord OccurrenceException is ordered chronologically + advanceExceptions :: (Integer, Set OccurrenceException) -> OccurrenceException -> (Integer, Set OccurrenceException) + advanceExceptions (offset, acc) ex + | ed `Set.notMember` offDays -- skip term-holidays and weekends, unless the original day was a holiday or weekend + , nd `Set.member` offDays + = advanceExceptions (succ offset, acc) ex + | otherwise + = (offset, Set.insert (setDayOfOccurrenceException nd ex) acc) + where + ed = dayOfOccurrenceException ex + nd = addDays offset ed diff --git a/src/Handler/Utils/Table/Pagination.hs b/src/Handler/Utils/Table/Pagination.hs index d3852d2eb..5b44a4b75 100644 --- a/src/Handler/Utils/Table/Pagination.hs +++ b/src/Handler/Utils/Table/Pagination.hs @@ -1446,8 +1446,8 @@ dbTable PSValidator{..} dbtable@DBTable{ dbtIdent = dbtIdent'@(toPathPiece -> db let rowCount = fromMaybe 0 $ rows' ^? _head . _1 . _Value - -- | selectPagesize = fromMaybe 0 $ rows' ^? _head . _1 . _Value - -- | otherwise = olength64 rows + -- | selectPagesize = fromMaybe 0 $ rows' ^? _head . _1 . _Value + -- | otherwise = olength64 rows rawAction = tblLink $ setParam (wIdent "sorting") Nothing diff --git a/src/Handler/Utils/Term.hs b/src/Handler/Utils/Term.hs index 49ef41a87..841082745 100644 --- a/src/Handler/Utils/Term.hs +++ b/src/Handler/Utils/Term.hs @@ -6,6 +6,7 @@ module Handler.Utils.Term ( groupHolidays , getCurrentTerm , getActiveTerms + , fetchTermByCID , module Utils.Term ) where @@ -61,3 +62,17 @@ getActiveTerms = do fmap Set.fromDistinctAscList . runConduit $ E.selectSource activeTermsQuery .| C.map E.unValue .| C.sinkList + +fetchTermByCID :: ( MonadHandler m + , BackendCompatible SqlBackend backend + , PersistQueryRead backend, PersistUniqueRead backend + ) + => CourseId -> ReaderT backend m Term +fetchTermByCID cid = do + termList <- E.select . E.distinct . E.from $ \(course `E.InnerJoin` term) -> do + E.on $ course E.^. CourseTerm E.==. term E.^. TermId + E.where_ $ course E.^. CourseId E.==. E.val cid + return term + case termList of + [term] -> return $ entityVal term + _other -> notFound \ No newline at end of file diff --git a/src/Jobs/Crontab.hs b/src/Jobs/Crontab.hs index d660e3552..e352758ef 100644 --- a/src/Jobs/Crontab.hs +++ b/src/Jobs/Crontab.hs @@ -324,7 +324,7 @@ determineCrontab = execWriterT $ do , jIteration = fromInteger nextInterval }) Cron - { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ nextIntervalTime + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ $ toTimeOfDay 23 30 0 $ utctDay nextIntervalTime , cronRepeat = CronRepeatNever , cronRateLimit = appSynchroniseLdapUsersInterval , cronNotAfter = Right . CronTimestamp . utcToLocalTimeTZ appTZ $ addUTCTime appSynchroniseLdapUsersInterval nextIntervalTime @@ -337,6 +337,8 @@ determineCrontab = execWriterT $ do , Just syncWithin <- appSynchroniseAvsUsersWithin , Just cInterval <- appJobCronInterval -> do + now <- liftIO getCurrentTime + let nowaday = utctDay now nextIntervals <- getNextIntervals syncWithin appSynchroniseAvsUsersInterval cInterval forM_ nextIntervals $ \(nextEpoch, nextInterval, nextIntervalTime, numIntervals) -> do @@ -345,12 +347,12 @@ determineCrontab = execWriterT $ do { jEpoch = fromInteger nextEpoch , jNumIterations = fromInteger numIntervals , jIteration = fromInteger nextInterval - , jSynchAfter = Nothing + , jSynchAfter = Just $ addDays (-7) nowaday -- at most once per week }) Cron - { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ nextIntervalTime + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ $ toTimeOfDay 22 0 0 $ utctDay nextIntervalTime , cronRepeat = CronRepeatNever - , cronRateLimit = appSynchroniseLdapUsersInterval + , cronRateLimit = appSynchroniseAvsUsersInterval , cronNotAfter = Right . CronTimestamp . utcToLocalTimeTZ appTZ $ addUTCTime appSynchroniseAvsUsersInterval nextIntervalTime } | otherwise @@ -367,28 +369,28 @@ determineCrontab = execWriterT $ do } ) Cron - { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ nextIntervalTime + { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ $ toTimeOfDay 22 0 0 $ utctDay nextIntervalTime , cronRepeat = CronRepeatNever , cronRateLimit = appPruneUnreferencedFilesInterval , cronNotAfter = Right . CronTimestamp . utcToLocalTimeTZ appTZ $ addUTCTime appPruneUnreferencedFilesInterval nextIntervalTime } - whenIsJust ((,) <$> appStudyFeaturesRecacheRelevanceWithin <*> appJobCronInterval) $ \(within, cInterval) -> do - nextIntervals <- getNextIntervals within appStudyFeaturesRecacheRelevanceInterval cInterval - forM_ nextIntervals $ \(nextEpoch, nextInterval, nextIntervalTime, numIntervals) -> do - tell $ HashMap.singleton - (JobCtlQueue JobStudyFeaturesRecacheRelevance - { jEpoch = fromInteger nextEpoch - , jNumIterations = fromInteger numIntervals - , jIteration = fromInteger nextInterval - } - ) - Cron - { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ nextIntervalTime - , cronRepeat = CronRepeatNever - , cronRateLimit = appStudyFeaturesRecacheRelevanceInterval - , cronNotAfter = Right . CronTimestamp . utcToLocalTimeTZ appTZ $ addUTCTime appStudyFeaturesRecacheRelevanceInterval nextIntervalTime - } + -- whenIsJust ((,) <$> appStudyFeaturesRecacheRelevanceWithin <*> appJobCronInterval) $ \(within, cInterval) -> do + -- nextIntervals <- getNextIntervals within appStudyFeaturesRecacheRelevanceInterval cInterval + -- forM_ nextIntervals $ \(nextEpoch, nextInterval, nextIntervalTime, numIntervals) -> do + -- tell $ HashMap.singleton + -- (JobCtlQueue JobStudyFeaturesRecacheRelevance + -- { jEpoch = fromInteger nextEpoch + -- , jNumIterations = fromInteger numIntervals + -- , jIteration = fromInteger nextInterval + -- } + -- ) + -- Cron + -- { cronInitial = CronTimestamp $ utcToLocalTimeTZ appTZ toTimeOfDay 22 0 0 $ utctDay nextIntervalTime + -- , cronRepeat = CronRepeatNever + -- , cronRateLimit = appStudyFeaturesRecacheRelevanceInterval + -- , cronNotAfter = Right . CronTimestamp . utcToLocalTimeTZ appTZ $ addUTCTime appStudyFeaturesRecacheRelevanceInterval nextIntervalTime + -- } whenIsJust appQualificationCheckHour $ \hour -> tell $ HashMap.singleton (JobCtlQueue JobLmsQualificationsEnqueue) diff --git a/src/Jobs/Handler/LMS.hs b/src/Jobs/Handler/LMS.hs index 0a701784e..56273ca8b 100644 --- a/src/Jobs/Handler/LMS.hs +++ b/src/Jobs/Handler/LMS.hs @@ -62,10 +62,37 @@ dispatchJobLmsEnqueue qid = JobHandlerAtomic act $logInfoS "LMS" $ "Notifying about exipiring qualification " <> qshort now <- liftIO getCurrentTime case qualificationRefreshWithin quali of - Nothing -> return () -- no automatic scheduling for this qid + Nothing -> return () -- TODO: no renewal period, no reminders currenty (Just renewalPeriod) -> do let nowaday = utctDay now renewalDate = addGregorianDurationClip renewalPeriod nowaday + sendReminders remindPeriod = do + let remindDate = addGregorianDurationClip remindPeriod nowaday + reminders <- E.select $ do -- TODO: refactor to remove some redundancies with later query + (luser :& quser) <- E.from $ E.table @LmsUser `E.innerJoin` E.table @QualificationUser + `E.on` (\(luser :& quser) -> luser E.^. LmsUserQualification E.==. quser E.^. QualificationUserQualification + E.&&. luser E.^. LmsUserUser E.==. quser E.^. QualificationUserUser + ) + E.where_ $ quser E.^. QualificationUserQualification E.==. E.val qid + E.&&. quser E.^. QualificationUserScheduleRenewal + E.&&. quser E.^. QualificationUserValidUntil E.<=. E.val remindDate + E.&&. validQualification now quser + E.&&. E.isNothing (luser E.^. LmsUserEnded) + E.&&. E.isNothing (luser E.^. LmsUserStatus) + E.&&. E.isJust (luser E.^. LmsUserNotified) + -- E.&&. ((day_ (luser E.^. LmsUserNotified) E.+. E.interval remindPeriod) E.<. quser E.^. QualificationUserValidUntil) -- not sure whether may throw runtime errors, so we check in Haskell-Land instead + return (luser, quser E.^. QualificationUserValidUntil) + forM_ reminders $ \case + (Entity _ LmsUser{lmsUserUser=luser, lmsUserNotified=Just lnotified}, E.Value quValidUntil) + | addGregorianDurationClip remindPeriod (utctDay lnotified) < quValidUntil -> + queueDBJob JobUserNotification + { jRecipient = luser + , jNotification = NotificationQualificationRenewal { nQualification = qid, nReminder = True } + } + _ -> return () + -- send second reminders first, before enqueing even more + ifMaybeM (qualificationRefreshReminder quali) () sendReminders + renewalUsers <- E.select $ do quser <- E.from $ E.table @QualificationUser E.where_ $ quser E.^. QualificationUserQualification E.==. E.val qid @@ -85,7 +112,7 @@ dispatchJobLmsEnqueue qid = JobHandlerAtomic act uex = quser ^. _entityVal . _qualificationUserValidUntil in if qualificationElearningStart quali then JobLmsEnqueueUser { jQualification = qid, jUser = uid } - else JobSendNotification { jRecipient = uid, jNotification = + else JobUserNotification { jRecipient = uid, jNotification = NotificationQualificationExpiry { nQualification = qid, nExpiry = uex } } forM_ renewalUsers (queueDBJob . usr_job) @@ -97,11 +124,11 @@ dispatchJobLmsEnqueueUser qid uid = JobHandlerAtomic act act = do identsInUseVs <- E.select $ do lui <- E.from $ - ( (E.^. LmsUserlistIdent) <$> E.from (E.table @LmsUserlist) ) + ( (E.^. LmsUserlistIdent) <$> E.from (E.table @LmsUserlist) ) -- no filter by Qid, since LmsIdents must be unique across all `E.union_` - ( (E.^. LmsResultIdent) <$> E.from (E.table @LmsResult) ) + ( (E.^. LmsResultIdent) <$> E.from (E.table @LmsResult ) ) `E.union_` - ( (E.^. LmsUserIdent) <$> E.from (E.table @LmsUser) ) + ( (E.^. LmsUserIdent) <$> E.from (E.table @LmsUser ) ) E.orderBy [E.asc lui] pure lui now <- liftIO getCurrentTime @@ -149,27 +176,31 @@ dispatchJobLmsDequeue qid = JobHandlerAtomic act `E.on` (\(quser :& luser) -> luser E.^. LmsUserUser E.==. quser E.^. QualificationUserUser E.&&. luser E.^. LmsUserQualification E.==. quser E.^. QualificationUserQualification) - E.where_ $ E.isNothing (luser E.^. LmsUserStatus) + E.where_ $ quser E.^. QualificationUserQualification E.==. E.val qid + E.&&. luser E.^. LmsUserQualification E.==. E.val qid + E.&&. E.isNothing (luser E.^. LmsUserStatus) E.&&. E.isNothing (luser E.^. LmsUserEnded) E.&&. E.not_ (validQualification now quser) pure (luser E.^. LmsUserId) nrExpired <- E.updateCount $ \luser -> do E.set luser [LmsUserStatus E.=. E.justVal (LmsExpired nowaday)] E.where_ $ (luser E.^. LmsUserId) `E.in_` E.valList (E.unValue <$> expiredLearners) + E.&&. luser E.^. LmsUserQualification E.==. E.val qid $logInfoS "LMS" $ "Expired lms users " <> tshow nrExpired <> " for qualification " <> qshort - notifyInvalidDrivers <- E.select $ do - quser <- E.from $ E.table @QualificationUser - E.where_ $ E.not_ (quser `qualificationValid` now) -- currently invalid - E.&&. quser E.^. QualificationUserQualification E.==. E.val qid -- correct qualification - E.&&. quser `quserToNotify` now -- recently became invalid or blocked - pure (quser E.^. QualificationUserUser) - - forM_ notifyInvalidDrivers $ \(E.Value uid) -> - queueDBJob JobSendNotification - { jRecipient = uid - , jNotification = NotificationQualificationExpired { nQualification = qid } - } + when (quali ^. _qualificationExpiryNotification) $ do + notifyInvalidDrivers <- E.select $ do + quser <- E.from $ E.table @QualificationUser + E.where_ $ E.not_ (quser `qualificationValid` now) -- currently invalid + E.&&. quser E.^. QualificationUserQualification E.==. E.val qid -- correct qualification + E.&&. quser `quserToNotify` now -- recently became invalid or blocked + pure (quser E.^. QualificationUserUser) + + forM_ notifyInvalidDrivers $ \(E.Value uid) -> + queueDBJob JobUserNotification + { jRecipient = uid + , jNotification = NotificationQualificationExpired { nQualification = qid } + } -- purge outdated LmsUsers case qualificationAuditDuration quali of @@ -234,7 +265,7 @@ dispatchJobLmsResults qid = JobHandlerAtomic act -- WORKAROUND LMS-Bug [supposedly fixed now, but isnt]: sometimes we receive success and failure simultaneously; success is correct, hence we must unblock if the reason was e-learning let reason_undo = Left $ "LMS Workaround undoing: " <> qualificationBlockedReasonText QualificationBlockFailedELearning ok_unblock <- qualificationUserUnblockByReason qid [qualificationUserUser] (Right QualificationBlockFailedELearning) reason_undo False -- affects audit log - when (ok_unblock > 0) ($logWarnS "LmsResult" [st|LMS workaround triggered, unblocking #{tshow ok_unblock} e-learners for #{tshow qid}|]) + when (ok_unblock > 0) ($logWarnS "LMS" [st|LMS Result: workaround triggered, unblocking #{tshow ok_unblock} e-learners for #{tshow qid}|]) _ok_renew <- renewValidQualificationUsers qid [qualificationUserUser] -- ignores possible blocks -- when (ok==1) $ update luid -- we end lms regardless of whether or not a regular renewal was successful, since BPol users may simultaneoysly have on-premise renewal courses and E-Learnings @@ -245,8 +276,8 @@ dispatchJobLmsResults qid = JobHandlerAtomic act ] return Nothing else do - let errmsg = [st|LMS success with insane date #{tshow lmsResultSuccess} received for #{tshow lmsUserIdent} for #{tshow qid}|] - $logErrorS "LmsResult" errmsg + let errmsg = [st|LMS Result: success with insane date #{tshow lmsResultSuccess} received for #{tshow lmsUserIdent} for #{tshow qid}|] + $logErrorS "LMS" errmsg return $ Just errmsg audit TransactionLmsSuccess -- always log success, since this is only transmitted once @@ -258,7 +289,7 @@ dispatchJobLmsResults qid = JobHandlerAtomic act , transactionReceived = lmsResultTimestamp } delete lrid - $logInfoS "LmsResult" [st|Processed #{tshow (length results)} LMS results|] + $logInfoS "LMS" [st|Processed #{tshow (length results)} LMS results|] -- processes received input and block qualifications, if applicable @@ -267,7 +298,7 @@ dispatchJobLmsUserlist qid = JobHandlerAtomic act where act :: YesodJobDB UniWorX () act = do - now <- liftIO getCurrentTime + now <- liftIO getCurrentTime -- result :: [(Entity LmsUser, Entity LmsUserlist)] results <- E.select $ do (luser :& lulist) <- E.from $ @@ -287,13 +318,12 @@ dispatchJobLmsUserlist qid = JobHandlerAtomic act (Entity luid luser, Just (Entity _lulid lulist)) -> do let lReceived = lmsUserlistTimestamp lulist lmsMsgDay = utctDay lReceived - update luid [LmsUserReceived =. Just lReceived] -- LmsUserNotified is only updated upon sending notifications - -- $logInfoS "LmsUserlist" $ tshow lulist + update luid [LmsUserReceived =. Just lReceived] -- LmsUserNotified is only updated upon sending notifications when (isNothing $ lmsUserNotified luser) $ do -- notify users that lms is available - queueDBJob JobSendNotification + queueDBJob JobUserNotification { jRecipient = lmsUserUser luser - , jNotification = NotificationQualificationRenewal { nQualification = qid } + , jNotification = NotificationQualificationRenewal { nQualification = qid, nReminder = False } } let isBlocked = lmsUserlistFailed lulist @@ -315,4 +345,4 @@ dispatchJobLmsUserlist qid = JobHandlerAtomic act , transactionReceived = lReceived } delete lulid - $logInfoS "LmsUserlist" [st|Processed LMS Userlist with ${tshow (length results)} entries|] + $logInfoS "LMS" [st|Processed LMS Userlist with #{tshow (length results)} entries|] diff --git a/src/Jobs/Handler/QueueNotification.hs b/src/Jobs/Handler/QueueNotification.hs index db91f4640..a4a407afa 100644 --- a/src/Jobs/Handler/QueueNotification.hs +++ b/src/Jobs/Handler/QueueNotification.hs @@ -4,6 +4,7 @@ module Jobs.Handler.QueueNotification ( dispatchJobQueueNotification + , classifyNotification ) where import Import @@ -175,11 +176,11 @@ determineNotificationCandidates = awaitForever $ \notif -> do classifyNotification :: Notification -> DB NotificationTrigger -classifyNotification NotificationSubmissionRated{..} = do - Sheet{sheetType} <- belongsToJust submissionSheet =<< getJust nSubmission - return $ case sheetType of - NotGraded -> NTSubmissionRated - _other -> NTSubmissionRatedGraded +classifyNotification NotificationSubmissionRated{..} = + maybeM (return NTSubmissionRatedGraded) (fmap aux . belongsToJust submissionSheet) (get nSubmission) + where + aux Sheet{sheetType=NotGraded} = NTSubmissionRated + aux _other = NTSubmissionRatedGraded classifyNotification NotificationSheetActive{} = return NTSheetActive classifyNotification NotificationSheetHint{} = return NTSheetHint classifyNotification NotificationSheetSolution{} = return NTSheetSolution @@ -201,6 +202,8 @@ classifyNotification NotificationCourseRegistered{} = return NTCou classifyNotification NotificationSubmissionEdited{} = return NTSubmissionEdited classifyNotification NotificationSubmissionUserCreated{} = return NTSubmissionUserCreated classifyNotification NotificationSubmissionUserDeleted{} = return NTSubmissionUserDeleted -classifyNotification NotificationQualificationExpiry{} = return NTQualification -classifyNotification NotificationQualificationExpired{} = return NTQualification -classifyNotification NotificationQualificationRenewal{} = return NTQualification +classifyNotification NotificationQualificationExpiry{} = return NTQualificationExpiry +classifyNotification NotificationQualificationExpired{} = return NTQualificationExpiry +classifyNotification NotificationQualificationRenewal{nReminder} + | nReminder = return NTQualificationReminder + | otherwise = return NTQualificationExpiry diff --git a/src/Jobs/Handler/SendNotification.hs b/src/Jobs/Handler/SendNotification.hs index 8ed3370d5..198a7f2d8 100644 --- a/src/Jobs/Handler/SendNotification.hs +++ b/src/Jobs/Handler/SendNotification.hs @@ -4,6 +4,7 @@ module Jobs.Handler.SendNotification ( dispatchJobSendNotification + , dispatchJobUserNotification ) where import Import @@ -24,7 +25,21 @@ import Jobs.Handler.SendNotification.ExamOffice import Jobs.Handler.SendNotification.CourseRegistered import Jobs.Handler.SendNotification.SubmissionEdited import Jobs.Handler.SendNotification.Qualification +import Jobs.Handler.QueueNotification (classifyNotification) +-- | send a notification directly, ignoring userNotificationSettings, assumed to be checked bt dispatchJobQueueNotification dispatchJobSendNotification :: UserId -> Notification -> JobHandler UniWorX dispatchJobSendNotification jRecipient jNotification = JobHandlerException $ $(dispatchTH ''Notification) jNotification jRecipient + +-- | like `dispatchJobSendNotification` but checks userNotificationSettings first +dispatchJobUserNotification :: UserId -> Notification -> JobHandler UniWorX +dispatchJobUserNotification jRecipient jNotification = JobHandlerException $ do + ok <- runDB $ do + nTrigger <- classifyNotification jNotification + get jRecipient <&> \case + Just User{userNotificationSettings} + -> notificationAllowed userNotificationSettings nTrigger + _ -> False + when ok $ + $(dispatchTH ''Notification) jNotification jRecipient \ No newline at end of file diff --git a/src/Jobs/Handler/SendNotification/Qualification.hs b/src/Jobs/Handler/SendNotification/Qualification.hs index 22dadc99d..d5338acf6 100644 --- a/src/Jobs/Handler/SendNotification/Qualification.hs +++ b/src/Jobs/Handler/SendNotification/Qualification.hs @@ -60,17 +60,17 @@ dispatchNotificationQualificationExpired nQualification jRecipient = do let expDay = maybe qualificationUserValidUntil (min qualificationUserValidUntil . utctDay . qualificationUserBlockFrom) block qname = CI.original qualificationName qshort = CI.original qualificationShorthand - letter = LetterExpireQualificationF - { leqfHolderCFN = encRecShort - , leqfHolderID = jRecipient - , leqfHolderDN = userDisplayName - , leqfHolderSN = userSurname - , leqfExpiry = Just expDay - , leqfId = nQualification - , leqfName = qname - , leqfShort = qshort - , leqfSchool = qualificationSchool - , leqfUrl = pure . urender $ ForProfileDataR encRecipient + letter = LetterExpireQualification + { leqHolderCFN = encRecShort + , leqHolderID = jRecipient + , leqHolderDN = userDisplayName + , leqHolderSN = userSurname + , leqExpiry = Just expDay + , leqId = nQualification + , leqName = qname + , leqShort = qshort + , leqSchool = qualificationSchool + , leqUrl = pure . urender $ ForProfileDataR encRecipient } if expDay > utctDay qualificationUserLastNotified then do @@ -86,8 +86,8 @@ dispatchNotificationQualificationExpired nQualification jRecipient = do -- NOTE: Renewal expects that LmsUser already exists for recipient -dispatchNotificationQualificationRenewal :: QualificationId -> UserId -> Handler () -dispatchNotificationQualificationRenewal nQualification jRecipient = do +dispatchNotificationQualificationRenewal :: QualificationId -> Bool -> UserId -> Handler () +dispatchNotificationQualificationRenewal nQualification nReminder jRecipient = do encRecipient :: CryptoUUIDUser <- encrypt jRecipient query <- runDB $ (,,,) <$> get jRecipient @@ -109,6 +109,7 @@ dispatchNotificationQualificationRenewal nQualification jRecipient = do , qualShort = CI.original qualificationShorthand , qualSchool = qualificationSchool , qualDuration = qualificationValidDuration + , isReminder = nReminder } $logInfoS "LMS" $ "Notify " <> tshow encRecipient <> " for renewal of qualification " <> qname notifyOk <- sendEmailOrLetter jRecipient letter diff --git a/src/Jobs/Handler/SynchroniseAvs.hs b/src/Jobs/Handler/SynchroniseAvs.hs index 5fd2807dd..96ae456df 100644 --- a/src/Jobs/Handler/SynchroniseAvs.hs +++ b/src/Jobs/Handler/SynchroniseAvs.hs @@ -1,23 +1,29 @@ --- SPDX-FileCopyrightText: 2022-23 Gregor Kleen , Steffen Jost +-- SPDX-FileCopyrightText: 2022-23 Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later module Jobs.Handler.SynchroniseAvs - ( dispatchJobSynchroniseAvs + ( dispatchJobSynchroniseAvs , dispatchJobSynchroniseAvsId - , dispatchJobSynchroniseAvsUser + , dispatchJobSynchroniseAvsUser + , dispatchJobSynchroniseAvsNext + , dispatchJobSynchroniseAvsQueue ) where import Import +import qualified Database.Esqueleto.Legacy as E hiding (upsert) +import qualified Database.Esqueleto.PostgreSQL as E +import qualified Database.Esqueleto.Utils as E + import qualified Data.Conduit.List as C import Jobs.Queue import Handler.Utils.Avs --- TODO: JobSynchroniseAllAvs is not yet scheduled in Crontab -dispatchJobSynchroniseAvs :: Natural -> Natural -> Natural -> Maybe UTCTime -> JobHandler UniWorX +dispatchJobSynchroniseAvs :: Natural -> Natural -> Natural -> Maybe Day -> JobHandler UniWorX dispatchJobSynchroniseAvs numIterations epoch iteration pause + -- TODO: refactor so that the AvsIdLookup becomes obsolete = JobHandlerAtomic . runConduit $ readUsers .| filterIteration .| sinkDBJobs where @@ -30,23 +36,69 @@ dispatchJobSynchroniseAvs numIterations epoch iteration pause userIteration, currentIteration :: Integer userIteration = toInteger (hash epoch `hashWithSalt` userId) `mod` toInteger numIterations currentIteration = toInteger iteration `mod` toInteger numIterations - $logDebugS "SynchronisAvs" [st|User ##{tshow (fromSqlKey userId)}: sync on #{tshow userIteration}/#{tshow numIterations}, now #{tshow currentIteration}|] + -- $logDebugS "SynchronisAvs" [st|User ##{tshow (fromSqlKey userId)}: sync on #{tshow userIteration}/#{tshow numIterations}, now #{tshow currentIteration}|] guard $ userIteration == currentIteration return $ JobSynchroniseAvsUser userId pause +-- dispatchJobSynchroniseAvs' :: Natural -> Natural -> Natural -> Maybe Day -> JobHandler UniWorX +-- dispatchJobSynchroniseAvs' numIterations epoch iteration pause = JobHandlerAtomic $ do -workJobSynchroniseAvs :: Either AvsPersonId UserId -> Maybe UTCTime -> JobHandler UniWorX -workJobSynchroniseAvs eauid pause = JobHandlerException $ do - let uniqKey = either UniqueUserAvsId UniqueUserAvsUser eauid - runDB (getBy uniqKey) >>= \case - Nothing -> return () -- do not create new newers in this background job, only update existing - Just Entity{entityVal=UserAvs{..}} - | maybe False (userAvsLastSynch >=) pause -> return () -- we just updated this one within the given limit - | otherwise -> void $ upsertAvsUserById userAvsPersonId -- updates UserAvsLAstSynch -dispatchJobSynchroniseAvsId :: AvsPersonId -> Maybe UTCTime -> JobHandler UniWorX -dispatchJobSynchroniseAvsId = workJobSynchroniseAvs . Left +dispatchJobSynchroniseAvsId :: AvsPersonId -> Maybe Day -> JobHandler UniWorX +dispatchJobSynchroniseAvsId apid pause = JobHandlerException $ do + ok <- runDBJobs $ + getBy (UniqueUserAvsId apid) >>= \case + (Just Entity{entityVal=UserAvs{userAvsUser=uid}}) -> do -- known user + workJobSychronizeAvs uid pause + return True + Nothing -> -- unknown avsPersonId, attempt to create user + return False + -- flip (maybeM $ return False) (getBy $ UniqueUserAvsId apid) $ \Entity{entityVal=UserAvs{userAvsUser=uid}} -> do -- known user + -- workJobSychronizeAvs uid pause + -- return True + unless ok $ void $ maybeCatchAll $ upsertAvsUserById apid -dispatchJobSynchroniseAvsUser :: UserId -> Maybe UTCTime -> JobHandler UniWorX -dispatchJobSynchroniseAvsUser = workJobSynchroniseAvs . Right + +dispatchJobSynchroniseAvsUser :: UserId -> Maybe Day -> JobHandler UniWorX +dispatchJobSynchroniseAvsUser uid pause = JobHandlerException $ runDBJobs $ workJobSychronizeAvs uid pause + +workJobSychronizeAvs :: UserId -> Maybe Day -> JobDB () +workJobSychronizeAvs uid pause = do + now <- liftIO getCurrentTime + void $ E.upsert + AvsSync { avsSyncUser = uid + , avsSyncCreationTime = now + , avsSyncPause = pause + } + [ \oldSync -> (AvsSyncPause E.=. E.greatest (E.val pause) (oldSync E.^. AvsSyncPause)) oldSync ] + queueDBJob JobSynchroniseAvsQueue + +dispatchJobSynchroniseAvsQueue :: JobHandler UniWorX +dispatchJobSynchroniseAvsQueue = JobHandlerException $ do + syncJob <- runDB $ + selectFirst [] [Asc AvsSyncCreationTime] >>= \case + Nothing -> return Nothing -- nothing more to do + Just Entity{entityKey=asid, entityVal=AvsSync{..}} -> do + delete asid + getBy (UniqueUserAvsUser avsSyncUser) >>= \case + Just uae@Entity{entityVal=UserAvs{userAvsLastSynch} } + | maybe True (utctDay userAvsLastSynch <) avsSyncPause -> return $ Just uae + _other -> return Nothing -- we just updated this one within the given limit or the entity does not exist + + ifMaybeM syncJob () $ \Entity{entityKey=avsKey, entityVal=UserAvs{userAvsPersonId=apid}} -> do + void $ queueJob JobSynchroniseAvsNext + catch (void $ upsertAvsUserById apid) -- already updates UserAvsLastSynch + (\exc -> do + now <- liftIO getCurrentTime + let excMsg = tshow exc <> " at " <> tshow now + runDB (update avsKey [UserAvsLastSynchError =. Just excMsg, UserAvsLastSynch =. now]) + case exc of + AvsInterfaceUnavailable -> return () -- ignore and retry later + AvsUserUnknownByAvs _ -> return () -- ignore for users no longer listed in AVS + otherExc -> throwM otherExc + ) + +-- needed, since JobSynchroniseAvsQueue cannot requeue itself due to JobNoQueueSame (and having no parameters) +dispatchJobSynchroniseAvsNext :: JobHandler UniWorX +dispatchJobSynchroniseAvsNext = JobHandlerException $ void $ queueJob JobSynchroniseAvsQueue diff --git a/src/Jobs/Types.hs b/src/Jobs/Types.hs index 8325d40fc..60eee0b4c 100644 --- a/src/Jobs/Types.hs +++ b/src/Jobs/Types.hs @@ -55,6 +55,7 @@ import Data.Generics.Product.Types (Children, ChGeneric, HasTypesCustom(..)) data Job = JobSendNotification { jRecipient :: UserId, jNotification :: Notification } + | JobUserNotification { jRecipient :: UserId, jNotification :: Notification } | JobSendTestEmail { jEmail :: Email, jMailContext :: MailContext } | JobQueueNotification { jNotification :: Notification } | JobHelpRequest { jHelpSender :: Either (Maybe Address) UserId @@ -92,14 +93,16 @@ data Job | JobSynchroniseAvs { jNumIterations , jEpoch , jIteration :: Natural - , jSynchAfter :: Maybe UTCTime + , jSynchAfter :: Maybe Day } | JobSynchroniseAvsUser { jUser :: UserId - , jSynchAfter :: Maybe UTCTime - } - | JobSynchroniseAvsId { jAvsId:: AvsPersonId - , jSynchAfter :: Maybe UTCTime + , jSynchAfter :: Maybe Day } + | JobSynchroniseAvsId { jAvsId :: AvsPersonId + , jSynchAfter :: Maybe Day + } + | JobSynchroniseAvsQueue + | JobSynchroniseAvsNext | JobChangeUserDisplayEmail { jUser :: UserId , jDisplayEmail :: UserEmail } @@ -151,9 +154,9 @@ data Notification | NotificationSubmissionEdited { nInitiator :: UserId, nSubmission :: SubmissionId } | NotificationSubmissionUserCreated { nUser :: UserId, nSubmission :: SubmissionId } | NotificationSubmissionUserDeleted { nUser :: UserId, nSheet :: SheetId, nSubmission :: SubmissionId } - | NotificationQualificationExpiry { nQualification :: QualificationId, nExpiry :: Day } - | NotificationQualificationExpired { nQualification :: QualificationId } - | NotificationQualificationRenewal { nQualification :: QualificationId } + | NotificationQualificationExpiry { nQualification :: QualificationId, nExpiry :: Day } -- NotificationTrigger: NTQualificationExpiry TODO: separate + | NotificationQualificationExpired { nQualification :: QualificationId } -- NotificationTrigger: NTQualificationExpiry + | NotificationQualificationRenewal { nQualification :: QualificationId, nReminder :: Bool } -- NotificationTrigger: NTQualificationExpiry/NTQualificationReminder je nach nReminder deriving (Eq, Ord, Show, Read, Generic) instance Hashable Job @@ -331,13 +334,18 @@ data JobNoQueueSame = JobNoQueueSame | JobNoQueueSameTag jobNoQueueSame :: Job -> Maybe JobNoQueueSame jobNoQueueSame = \case JobSendNotification{jNotification} -> notifyNoQueueSame jNotification + JobUserNotification{jNotification} -> notifyNoQueueSame jNotification JobSendPasswordReset{} -> Just JobNoQueueSame JobTruncateTransactionLog{} -> Just JobNoQueueSame JobPruneInvitations{} -> Just JobNoQueueSame JobDeleteTransactionLogIPs{} -> Just JobNoQueueSame + JobSynchroniseLdap{} -> Just JobNoQueueSame JobSynchroniseLdapUser{} -> Just JobNoQueueSame + JobSynchroniseAvs{} -> Just JobNoQueueSame JobSynchroniseAvsUser{} -> Just JobNoQueueSame JobSynchroniseAvsId{} -> Just JobNoQueueSame + JobSynchroniseAvsQueue{} -> Just JobNoQueueSame + JobSynchroniseAvsNext{} -> Just JobNoQueueSame JobChangeUserDisplayEmail{} -> Just JobNoQueueSame JobPruneSessionFiles{} -> Just JobNoQueueSameTag JobPruneUnreferencedFiles{} -> Just JobNoQueueSameTag diff --git a/src/Model/Types/Avs.hs b/src/Model/Types/Avs.hs index f1937c736..dc58f1087 100644 --- a/src/Model/Types/Avs.hs +++ b/src/Model/Types/Avs.hs @@ -254,7 +254,7 @@ instance FromJSON AvsLicence where parseJSON (Number n) | n == 1 = pure AvsLicenceVorfeld -- ordered by occurrence, n==1 is most common case | n == 2 = pure AvsLicenceRollfeld | n == 0 = pure AvsNoLicence - -- | n ==(-1) = pure AvsNoLicenceGuest -- InfoContact may send -1 for Guest unable to obtain a licence + {- | n ==(-1) = pure AvsNoLicenceGuest -- InfoContact may send -1 for Guest unable to obtain a licence -} #ifdef DEVELOPMENT parseJSON invalid = prependFailure "parsing AvsLicence failed, " $ fail $ "expected Int value being 0, 1 or 2. Found " ++ show invalid #else diff --git a/src/Model/Types/DateTime.hs b/src/Model/Types/DateTime.hs index f36420657..bc31638b4 100644 --- a/src/Model/Types/DateTime.hs +++ b/src/Model/Types/DateTime.hs @@ -15,12 +15,13 @@ module Model.Types.DateTime import Import.NoModel -import qualified Data.Set as Set +-- import qualified Data.Set as Set import Data.Ratio ((%)) import qualified Data.Text as Text -- import Data.Either.Combinators (maybeToRight, mapLeft) import Text.Read (readMaybe) +-- import Data.Time.LocalTime import Data.Time.Calendar.WeekDate -- import Data.Time.Format.ISO8601 @@ -184,15 +185,34 @@ data OccurrenceException = ExceptOccur | ExceptNoOccur { exceptTime :: LocalTime } - deriving (Eq, Ord, Read, Show, Generic) + deriving (Eq, Read, Show, Generic) deriving anyclass (NFData) +-- Handler.Utils.Occurrences.occurrencesAddBusinessDays assumes that OccurrenceException is ordered chronologically +instance Ord OccurrenceException where + compare ExceptOccur{exceptDay=ad, exceptStart=as, exceptEnd=ae} ExceptOccur{exceptDay=bd, exceptStart=bs, exceptEnd=be} + = compare (ad,as,ae) (bd,bs,be) + compare ExceptOccur{exceptDay=d, exceptStart=s} ExceptNoOccur{exceptTime=e} + = replaceEq LT $ compare (LocalTime d s) e + compare ExceptNoOccur{exceptTime=e } ExceptOccur{exceptDay=d, exceptStart=s} + = replaceEq GT $ compare e (LocalTime d s) + compare ExceptNoOccur{exceptTime=ae } ExceptNoOccur{exceptTime=be } + = compare ae be + deriveJSON defaultOptions { fieldLabelModifier = camelToPathPiece' 1 , constructorTagModifier = camelToPathPiece' 1 , sumEncoding = TaggedObject "exception" "for" } ''OccurrenceException +dayOfOccurrenceException :: OccurrenceException -> Day +dayOfOccurrenceException ExceptOccur{exceptDay=d} = d +dayOfOccurrenceException ExceptNoOccur{exceptTime=LocalTime{localDay=d}} = d + +setDayOfOccurrenceException :: Day -> OccurrenceException -> OccurrenceException +setDayOfOccurrenceException d ex@ExceptOccur{} = ex{exceptDay=d} +setDayOfOccurrenceException d ExceptNoOccur{exceptTime=t} = ExceptNoOccur{exceptTime = t{localDay=d}} + data Occurrences = Occurrences { occurrencesScheduled :: Set OccurrenceSchedule , occurrencesExceptions :: Set OccurrenceException @@ -209,14 +229,21 @@ derivePersistFieldJSON ''Occurrences nullaryPathPiece ''DayOfWeek camelToPathPiece --- | Get bounds for an Occurrences --- TODO: unfinished function, only works for a few selected cases yet -occurrencesBounds :: Occurrences -> (Maybe Day, Maybe Day) -occurrencesBounds Occurrences{occurrencesScheduled=scd} | notNull scd = (Nothing, Nothing) -- TODO: case is not yet implemented -occurrencesBounds Occurrences{occurrencesExceptions=exc} = (Set.lookupMin occDays, Set.lookupMax occDays) - where - occDays = Set.foldr getOccDays mempty exc - - getOccDays :: OccurrenceException -> Set Day -> Set Day - getOccDays ExceptNoOccur{} acc = acc -- TODO: this case ignores ExceptNoOccur for now! - getOccDays ExceptOccur{exceptDay} acc = Set.insert exceptDay acc +-- test :: IO [OccurrenceException] +-- test = do +-- now <- getCurrentTime +-- tz <- getCurrentTimeZone +-- let lt1 = utcToLocalTime tz now +-- tomorrow = addUTCTime nominalDay now +-- lt2 = utcToLocalTime tz tomorrow +-- yesterday = addUTCTime (negate nominalDay) now +-- lt3 = utcToLocalTime tz yesterday +-- pure +-- [ ExceptOccur (utctDay tomorrow ) midday midnight +-- , ExceptOccur (utctDay now ) midnight midnight +-- , ExceptOccur (utctDay now ) midday midnight +-- , ExceptOccur (utctDay yesterday) midday midnight +-- , ExceptNoOccur lt3 +-- , ExceptNoOccur lt1 +-- , ExceptNoOccur lt2 +-- ] \ No newline at end of file diff --git a/src/Model/Types/Mail.hs b/src/Model/Types/Mail.hs index cba46cefd..1b6223e10 100644 --- a/src/Model/Types/Mail.hs +++ b/src/Model/Types/Mail.hs @@ -60,7 +60,8 @@ data NotificationTrigger | NTExamOfficeExamResults | NTExamOfficeExamResultsChanged | NTCourseRegistered - | NTQualification + | NTQualificationExpiry + | NTQualificationReminder deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic) deriving anyclass (Universe, Finite, Hashable, NFData) diff --git a/src/Utils.hs b/src/Utils.hs index 226b84bbc..a069b340b 100644 --- a/src/Utils.hs +++ b/src/Utils.hs @@ -628,8 +628,8 @@ trd3 :: (a,b,c) -> c trd3 (_,_,z) = z -- Further projections are available via TemplateHaskell, defined in Utils.Common: --- $(projN n m) :: (t1,..,tn) -> tm (for m<=n) --- snd3 = $(projNI 3 2) +-- $(projN n m) :: (t1,..,tn) -> tm (for m<=n) +-- snd3 = $(projNI 3 2) mTuple :: Applicative f => f a -> f b -> f (a, b) mTuple = liftA2 (,) @@ -870,12 +870,13 @@ deepAlt altFst _ = altFst maybeEmpty :: Monoid m => Maybe a -> (a -> m) -> m maybeEmpty = flip foldMap + -- The more general `find :: Foldable t => (a -> Bool) -> t a -> Maybe a` filterMaybe :: (a -> Bool) -> Maybe a -> Maybe a filterMaybe c r@(Just x) | c x = r filterMaybe _ _ = Nothing --- | also referred to as whenJust +-- | also referred to as whenJust and forM_ whenIsJust :: Monad m => Maybe a -> (a -> m ()) -> m () whenIsJust (Just x) f = f x whenIsJust Nothing _ = return () @@ -1751,7 +1752,7 @@ maxOn = maxBy . comparing inBetween:: Ord a => a -> (a,a) -> Bool inBetween x (lower,upper) = lower <= x && x <= upper --- | Given to values and a criterion, returns the unique argument that fulfills the criterion, if it exists +-- | Given two values and a criterion, returns the unique argument that fulfills the criterion, if it exists pickBetter :: a -> a -> (a -> Bool) -> Maybe a pickBetter x y crit | cx == cy = Nothing @@ -1761,6 +1762,15 @@ pickBetter x y crit cx = crit x cy = crit y +reverseOrdering :: Ordering -> Ordering +reverseOrdering EQ = EQ +reverseOrdering GT = LT +reverseOrdering LT = GT + +replaceEq :: Ordering -> Ordering -> Ordering +replaceEq r EQ = r +replaceEq _ other = other + ------------ -- Random -- ------------ diff --git a/src/Utils/Avs.hs b/src/Utils/Avs.hs index 9f19af2b6..27932acda 100644 --- a/src/Utils/Avs.hs +++ b/src/Utils/Avs.hs @@ -101,7 +101,7 @@ splitQuery :: (Wrapped a, Wrapped c, Unwrapped a ~ Set b, Semigroup (Unwrapped c splitQuery rawQuery q | avsMaxQueryAtOnce >= Set.size s = rawQuery q | otherwise = do - -- $logInfoS "AVS" $ "Splitting large query for input Set " <> tshow (Set.size s) -- would require MonadLogger ClientM + -- logInfoS "AVS" $ "Splitting large query for input Set " <> tshow (Set.size s) -- would require MonadLogger ClientM let (avsid1, avsid2) = Set.splitAt avsMaxQueryAtOnce s res1 <- rawQuery $ view _Unwrapped' avsid1 res2 <- splitQuery rawQuery $ view _Unwrapped' avsid2 diff --git a/src/Utils/Csv/Mail.hs b/src/Utils/Csv/Mail.hs index f88fe6974..b14fc73cc 100644 --- a/src/Utils/Csv/Mail.hs +++ b/src/Utils/Csv/Mail.hs @@ -56,11 +56,11 @@ recodeCsv encOpts toUser act = fromMaybe act $ do inp <- C.sinkLazy inp' <- recode inp sourceLazy inp' .| act - -- -- | FormatXlsx <- fmt -> do - -- -- inp <- C.sinkLazy - -- -- archive <- throwLeft $ Zip.toArchiveOrFail inp - -- -- archive' <- traverseOf (_zEntries . traverse . _Entrty . _3) recode archive - -- -- sourceLazy (Zip.fromArchive inp') .| act + -- | FormatXlsx <- fmt -> do + -- inp <- C.sinkLazy + -- archive <- throwLeft $ Zip.toArchiveOrFail inp + -- archive' <- traverseOf (_zEntries . traverse . _Entrty . _3) recode archive + -- sourceLazy (Zip.fromArchive inp') .| act | otherwise -> act where diff --git a/src/Utils/DateTime.hs b/src/Utils/DateTime.hs index ca48f6b2c..fb08fa474 100644 --- a/src/Utils/DateTime.hs +++ b/src/Utils/DateTime.hs @@ -58,7 +58,7 @@ import Control.Monad.Fail import Utils.Lang (selectLanguage') --- $(timeLocaleMap _) :: [Lang] -> TimeLocale +-- Usage like so: $(timeLocaleMap _) :: [Lang] -> TimeLocale timeLocaleMap :: [(Lang, String)] -- ^ Languages and matching locales, first is taken as default -> ExpQ timeLocaleMap [] = fail "Need at least one (language, locale)-pair" diff --git a/src/Utils/Holidays.hs b/src/Utils/Holidays.hs index 649d0f16c..b8ae4fa18 100644 --- a/src/Utils/Holidays.hs +++ b/src/Utils/Holidays.hs @@ -150,11 +150,11 @@ index2year y = result -- | Test for Saturday/Sunday isWeekend :: Day -> Bool isWeekend = isWeekend' . dayOfWeek - where - isWeekend' :: WeekDay -> Bool - isWeekend' Sunday = True - isWeekend' Saturday = True - isWeekend' _ = False + +isWeekend' :: WeekDay -> Bool +isWeekend' Sunday = True +isWeekend' Saturday = True +isWeekend' _ = False -- | Always returns a business day. -- | Saturday/Sunday/Holiday treated like next (n>=0) or previous (n<0) working day diff --git a/src/Utils/Print.hs b/src/Utils/Print.hs index f1d3054de..313ffb333 100644 --- a/src/Utils/Print.hs +++ b/src/Utils/Print.hs @@ -1,4 +1,4 @@ --- SPDX-FileCopyrightText: 2022 Steffen Jost +-- SPDX-FileCopyrightText: 2022-23 Steffen Jost -- -- SPDX-License-Identifier: AGPL-3.0-or-later @@ -10,6 +10,7 @@ module Utils.Print , sendEmailOrLetter -- directly print or sends by email , printLetter -- always send a letter , printHtml -- return letter as Html only + , reprintPDF -- send a PDF once more the APC , letterApcIdent -- create acknowledge string for APC , letterFileName -- default filename , encryptPDF @@ -22,7 +23,7 @@ module Utils.Print -- , MDLetter , SomeLetter(..) , LetterRenewQualificationF(..) - , LetterExpireQualificationF(..) + , LetterExpireQualification(..) -- , LetterCourseCertificate() , makeCourseCertificates ) where @@ -211,9 +212,9 @@ renderLetters rcvrEnt@Entity{entityVal=rcvr} mdls apcIdent , toMeta "address" $ fromMaybe [rcvr & userDisplayName] $ getPostalAddress rcvr --, toMeta "rcvr-email" $ rcvr & userDisplayEmail -- note that some templates use "email" already otherwise ] - in mdTemplating tmpl meta >>= \case - err@Left{} -> pure err - Right doc2 -> pure $ Right $ doc1 <> doc2 + in mdTemplating tmpl meta <&> \case + err@Left{} -> err + Right doc2 -> Right $ doc1 <> doc2 doc <- foldrM templateCombine (Right mempty) mdls -- result <- actRight doc $ pdfLaTeX kind @@ -277,6 +278,20 @@ printLetter' pji pdf = do insert_ PrintJob {..} return $ Right (ok, printJobFilename) +reprintPDF :: PrintJobId -> DB (Either Text Text) +reprintPDF pjid = maybeM (return $ Left "Print job id is unknown.") reprint $ get pjid + where + reprint :: PrintJob -> DB (Either Text Text) + reprint pj@PrintJob{..} = do + result <- lprPDF printJobFilename $ LBS.fromStrict printJobFile + whenIsRight result $ const $ do + now <- liftIO getCurrentTime + insert_ pj{ printJobAcknowledged = Nothing + , printJobCreated = now + -- , printJobApcIdent = ??? cannot be modified here, since it is included inside the PDF + } + return result + {- printLetter'' :: _ -> DB PureFile printLetter'' _ = do @@ -287,18 +302,24 @@ printLetter'' _ = do } -} -sendEmailOrLetter :: (MDLetter l, MDMail l) => UserId -> l -> Handler Bool +sendEmailOrLetter :: (MDLetter l) => UserId -> l -> Handler Bool sendEmailOrLetter recipient letter = do (underling, receivers, undercopy) <- updateReceivers recipient -- TODO: check to avoid this almost circular dependency now <- liftIO getCurrentTime + mr <- getMessageRender let pjid = getPJId letter fName = letterFileName letter - mailSubject = getMailSubject letter -- these are only needed if sent by email, but we're lazy anyway - undername = underling ^. _userDisplayName -- nameHtml' underling - undermail = CI.original $ underling ^. _userEmail - mr <- getMessageRender - let mailSupervisorSubject = SomeMessage $ "[SUPERVISOR] " <> mr mailSubject + -- these are only needed if sent by email, but we're lazy anyway + undername = underling ^. _userDisplayName -- nameHtml' underling + undermail = CI.original $ underling ^. _userEmail + mailSubjectRaw = getMailSubject letter + mailSubjectSuper = SomeMessage $ "[SUPERVISOR] " <> mr mailSubjectRaw + mkMailSubject = bool mailSubjectRaw mailSubjectSuper + mkMailBody = getMailBody letter oks <- forM receivers $ \rcvrEnt@Entity{ entityKey = svr, entityVal = rcvrUsr } -> do + let supername = rcvrUsr ^. _userDisplayName -- nameHtml' rcvrUsr + isSupervised = recipient /= svr + mailSubject = mkMailSubject isSupervised encRecipient :: CryptoUUIDUser <- encrypt svr apcIdent <- letterApcIdent letter encRecipient now case getPostalPreferenceAndAddress rcvrUsr of @@ -323,7 +344,7 @@ sendEmailOrLetter recipient letter = do $logWarnS "LETTER" $ "PDF printing to send letter with lpr returned ExitSuccess and the following message: " <> msg return True - (False, _) | attachPDFLetter letter -> renderLetterPDF rcvrEnt letter apcIdent >>= \case -- send Email, with pdf attached + (False, _) | Just mkMail <- mkMailBody -> renderLetterPDF rcvrEnt letter apcIdent >>= \case -- send Email, but with pdf attached Left err -> do -- pdf generation failed let msg = "Notification failed for " <> tshow encRecipient <> ". PDF attachment generation failed: "<> cropText err <> "For Notification: " <> tshow pjid $logErrorS "LETTER" msg @@ -342,14 +363,12 @@ sendEmailOrLetter recipient letter = do $logWarnS "LETTER" msg return pdf formatter <- getDateTimeFormatterUser' rcvrUsr -- not too expensive, only calls getTimeLocale - let isSupervised = recipient /= svr - supername = rcvrUsr ^. _userDisplayName -- nameHtml' rcvrUsr - mailBody <- getMailBody letter formatter + let mailBody = mkMail formatter userMailTdirect svr $ do replaceMailHeader "Auto-Submitted" $ Just "auto-generated" setSubjectI mailSubject editNotifications <- mkEditNotifications svr - addHtmlMarkdownAlternatives $(ihamletFile "templates/mail/genericMailLetter.hamlet") + addHtmlMarkdownAlternatives $(ihamletFile "templates/mail/genericMailLetter.hamlet") -- wrapper for mailBody addPart (File { fileTitle = fName , fileModified = now , fileContent = Just $ yield $ LBS.toStrict attachment @@ -361,18 +380,10 @@ sendEmailOrLetter recipient letter = do let msg = "Notification failed for " <> tshow encRecipient <> ". HTML generation failed: "<> cropText err <> "For Notification: " <> tshow pjid $logErrorS "LETTER" msg return False - Right html -> do -- html generated, send directly now - let isSupervised = recipient /= svr - -- subject = if isSupervised - -- then "[SUPERVISOR] " <> mailSubject - -- else mailSubject - subject = if isSupervised - then mailSupervisorSubject - else mailSubject + Right html -> do -- html generated, send directly now userMailTdirect svr $ do replaceMailHeader "Auto-Submitted" $ Just "auto-generated" - setSubjectI subject - -- when isSupervised $ mapSubject ("[SUPERVISOR] " <>) + setSubjectI mailSubject addHtmlMarkdownAlternatives html return True return $ or oks diff --git a/src/Utils/Print/CourseCertificate.hs b/src/Utils/Print/CourseCertificate.hs index 76d74533f..babcdfa54 100644 --- a/src/Utils/Print/CourseCertificate.hs +++ b/src/Utils/Print/CourseCertificate.hs @@ -16,6 +16,8 @@ import Data.FileEmbed (embedFile) import Utils.Print.Letters import Handler.Utils.Profile +-- import Handler.Utils.DateTime +import Handler.Utils.Occurrences data LetterCourseCertificate = LetterCourseCertificate { ccCourseId :: CourseId @@ -43,6 +45,7 @@ instance MDLetter LetterCourseCertificate where Text.replace "%%%course-content%%%" (unlines ccc) $ decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_qualification.md") getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_qualification.md") + getMailSubject l = SomeMessage . MsgCourseCertificate $ ccCourseName l letterMeta LetterCourseCertificate{..} DateTimeFormatter{ format } lang _rcvrEnt = mkMeta @@ -79,8 +82,10 @@ makeCourseCertificates Tutorial{ tutorialName = CI.original -> ccTutorialName , courseShorthand = CI.original -> ccCourseShorthand , courseSchool = CI.original . unSchoolKey -> ccCourseSchool , courseDescription = fmap html2textlines -> ccCourseContent + , courseTerm = termId } <- get404 ccCourseId - let (ccCourseBegin, ccCourseEnd) = eq2nothing $ occurrencesBounds occurrences + term <- get404 termId + let (ccCourseBegin, ccCourseEnd) = eq2nothing $ occurrencesBounds term occurrences forM participants $ \uid -> do User{userDisplayName=ccParticipant, userCompanyDepartment, userCompanyPersonalNumber} <- get404 uid (ccFraNumber, ccFraDepartment, ccCompany) <- diff --git a/src/Utils/Print/ExpireQualification.hs b/src/Utils/Print/ExpireQualification.hs index 1d73a3c6a..ddbba609e 100644 --- a/src/Utils/Print/ExpireQualification.hs +++ b/src/Utils/Print/ExpireQualification.hs @@ -7,7 +7,6 @@ module Utils.Print.ExpireQualification where import Import -import Text.Hamlet -- import Data.Char as Char -- import qualified Data.Text as Text @@ -16,75 +15,64 @@ import qualified Data.CaseInsensitive as CI import Data.FileEmbed (embedFile) import Utils.Print.Letters -import Handler.Utils.Widgets (nameHtml) -- , nameHtml') -data LetterExpireQualificationF = LetterExpireQualificationF - { leqfHolderCFN :: CryptoFileNameUser - , leqfHolderID :: UserId - , leqfHolderDN :: UserDisplayName - , leqfHolderSN :: UserSurname - , leqfExpiry :: Maybe Day - , leqfId :: QualificationId - , leqfName :: Text - , leqfShort :: Text - , leqfSchool :: SchoolId - , leqfUrl :: Maybe Text +data LetterExpireQualification = LetterExpireQualification + { leqHolderCFN :: CryptoFileNameUser + , leqHolderID :: UserId + , leqHolderDN :: UserDisplayName + , leqHolderSN :: UserSurname + , leqExpiry :: Maybe Day + , leqId :: QualificationId + , leqName :: Text + , leqShort :: Text + , leqSchool :: SchoolId + , leqUrl :: Maybe Text } deriving (Eq, Show) --- TODO: use markdown to generate the Letter -instance MDMail LetterExpireQualificationF where - attachPDFLetter _ = False - getMailSubject l = SomeMessage $ MsgMailSubjectQualificationExpired $ leqfShort l - getMailBody LetterExpireQualificationF{..} DateTimeFormatter{ format } = return $ - let expiryDate = format SelFormatDate <$> leqfExpiry - userDisplayName = leqfHolderDN - userSurname = leqfHolderSN - qualificationName = leqfName - qualificationShorthand = CI.mk leqfShort - qualificationSchool = leqfSchool - qname = qualificationName - ihamletSomeMessage _ _ _ = (mempty :: Html) -- TODO: use markdown for letter - editNotifications = () -- TODO: use markdown for letter - in $(ihamletFile "templates/mail/qualificationExpired.hamlet") - -- const $ const html - -- Html -> HtmlUrlI18n (SomeMessage UniWorX) (Route UniWorX) - -- foo _ _ html -> html - -- [shamlet|#Ansprache #{html}|] um Html umzuwandeln! - -- - -instance MDLetter LetterExpireQualificationF where +instance MDLetter LetterExpireQualification where encryptPDFfor _ = NoPassword getLetterKind _ = Din5008 getLetterEnvelope _ = 'e' - getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_f_expiry.md") + getMailSubject l = SomeMessage $ MsgMailSubjectQualificationExpired $ leqShort l - letterMeta LetterExpireQualificationF{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} = - let isSupervised = rcvrId /= leqfHolderID + getTemplate LetterExpireQualification{leqShort="F"} + = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_f_expiry.md") + getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_generic_expiry.md") + + + letterMeta LetterExpireQualification{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} = + let isSupervised = rcvrId /= leqHolderID in mkMeta $ guardMonoid isSupervised [ toMeta "supervisor" userDisplayName ] <> [ toMeta "lang" lang - , toMeta "licenceholder" leqfHolderDN - , mbMeta "expiry" (format SelFormatDate <$> leqfExpiry) - , mbMeta "licence-url" leqfUrl - , toMeta "de-opening" $ bool ("Guten Tag " <> leqfHolderDN <> ",") "Sehr geehrte Damen und Herren," isSupervised - , toMeta "en-opening" $ bool ("Dear " <> leqfHolderDN <> ",") "Dear supervisor," isSupervised + , toMeta "licencename" leqName + , toMeta "licenceshort" leqShort + , toMeta "licenceholder" leqHolderDN + , mbMeta "expiry" (format SelFormatDate <$> leqExpiry) + , mbMeta "licence-url" leqUrl + , toMeta "de-opening" $ bool ("Guten Tag " <> leqHolderDN <> ",") "Sehr geehrte Damen und Herren," isSupervised + , toMeta "en-opening" $ bool ("Dear " <> leqHolderDN <> ",") "Dear supervisor," isSupervised + , toMeta "de-subject" $ "Entzug \"" <> leqShort <> "\" (" <> leqName <> ")" + , toMeta "en-subject" $ case leqShort of + "F" -> "Revocation of apron driving license" + _ -> "Revocation of licence \"" <> leqShort <> "\" (" <> leqName <> ")" ] - getPJId LetterExpireQualificationF{..} = + getPJId LetterExpireQualification{..} = PrintJobIdentification { pjiName = "Expiry" - , pjiApcAcknowledge = "ex-" <> toPathPiece leqfHolderCFN + , pjiApcAcknowledge = "ex-" <> toPathPiece leqHolderCFN , pjiRecipient = Nothing -- to be filled later , pjiSender = Nothing , pjiCourse = Nothing - , pjiQualification = Just leqfId + , pjiQualification = Just leqId , pjiLmsUser = Nothing - , pjiFileName = "expire_" <> CI.original (unSchoolKey leqfSchool) <> "-" <> leqfShort <> "_" <> leqfHolderSN + , pjiFileName = "expire_" <> CI.original (unSchoolKey leqSchool) <> "-" <> leqShort <> "_" <> leqHolderSN -- let nameRecipient = abbrvName <$> recipient -- nameSender = abbrvName <$> sender -- nameCourse = CI.original . courseShorthand <$> course diff --git a/src/Utils/Print/Letters.hs b/src/Utils/Print/Letters.hs index 7fe8b4a68..0718a294b 100644 --- a/src/Utils/Print/Letters.hs +++ b/src/Utils/Print/Letters.hs @@ -188,6 +188,17 @@ mkApcIdent uuid envelope lk tnow apcAck = Text.filter apcAcceptedChars $ Text.in ensureLength :: Int -> Text -> Text ensureLength n = Text.take n . Text.justifyLeft n 'x' +formatApcIdentTime :: (HasLocalTime t, MonadHandler m) => t -> m Text +formatApcIdentTime = formatTime' "%y%m%d-%H" + +-- updateApcIdentTime :: UTCTime -> Text -> Text +-- updateApcIdentTime now oldapcident = do +-- tnow <- formatApcIdentTime now +-- let (st,en') = Text.splitAt (38 + 3 + 5 + 3) oldapcident -- TODO: ensure that the numbers are correct +-- en = Text.drop 9 en' +-- TODO: TEST whether the last characters in st and first characters in en are apcIdentSeparators and call error otherwise +-- return $ st <> ensureLength 9 tnow <> en + apcIdentSeparator :: Text apcIdentSeparator = Text.take 3 "___" -- must always have length 3 @@ -226,11 +237,14 @@ class MDLetter l where getLetterKind :: l -> LetterKind getTemplate :: l -> Text encryptPDFfor :: l -> EncryptPDFfor + getMailSubject :: l -> SomeMessage UniWorX -- currently only used as email subject + getMailBody :: l -> Maybe (DateTimeFormatter -> HtmlUrlI18n (SomeMessage UniWorX) (Route UniWorX)) -- Just returns cover-lettter for attaching PDF to, Nothing indicates that the letter should be sent as direct Html Email + getMailBody = const Nothing letterApcIdent :: (MDLetter l, MonadHandler m) => l -> CryptoUUIDUser -> UTCTime -> m Text letterApcIdent l uuid now = do -- now <- liftIO getCurrentTime - tnow <- formatTime' "%y%m%d-%H" now + tnow <- formatApcIdentTime now return $ mkApcIdent uuid (getLetterEnvelope l) (getLetterKind l) tnow (pjiApcAcknowledge $ getPJId l) letterFileName :: (MDLetter l) => l -> FilePath @@ -242,17 +256,3 @@ addApcIdent = P.Meta . toMeta "apc-ident" getApcIdent :: P.Meta -> Maybe Text getApcIdent (P.lookupMeta "apc-ident" -> Just (P.MetaString t)) = Just t getApcIdent _ = Nothing - - ----------------- --- Mail Class -- ----------------- - --- this is for letters that may alternatively be sent as attachments to emails - -class MDMail l where -- - getMailSubject :: l -> SomeMessage UniWorX -- only used if letter is sent by email as pdf attachment - getMailBody :: (MonadHandler m) => l -> DateTimeFormatter -> m (HtmlUrlI18n (SomeMessage UniWorX) (Route UniWorX)) -- only used if letter is sent by email as pdf attachment - -- | should the email also contain the letter as a PDF attachment? - attachPDFLetter :: l -> Bool - attachPDFLetter = const True diff --git a/src/Utils/Print/RenewQualification.hs b/src/Utils/Print/RenewQualification.hs index a7900105c..55d24c5cc 100644 --- a/src/Utils/Print/RenewQualification.hs +++ b/src/Utils/Print/RenewQualification.hs @@ -31,6 +31,7 @@ data LetterRenewQualificationF = LetterRenewQualificationF , qualShort :: Text , qualSchool :: SchoolId , qualDuration :: Maybe Int + , isReminder :: Bool } deriving (Eq, Show) @@ -46,17 +47,16 @@ letterRenewalQualificationFData LetterRenewQualificationF{lmsLogin} = LetterRene lmsUrlLogin = lmsUrl <> "/?login=" <> lmsIdent lmsIdent = getLmsIdent lmsLogin -instance MDMail LetterRenewQualificationF where - getMailSubject l = SomeMessage $ MsgMailSubjectQualificationRenewal $ qualShort l - getMailBody l@LetterRenewQualificationF{..} DateTimeFormatter{ format } = return $ - let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l - in $(ihamletFile "templates/mail/body/qualificationRenewal.hamlet") instance MDLetter LetterRenewQualificationF where - encryptPDFfor _ = PasswordUnderling + encryptPDFfor _ = PasswordUnderling getLetterKind _ = PinLetter getLetterEnvelope _ = 'f' -- maybe 'q' (Char.toLower . fst) $ Text.uncons (qualShort l) getTemplate _ = decodeUtf8 $(Data.FileEmbed.embedFile "templates/letter/fraport_renewal.md") + getMailSubject l = SomeMessage $ MsgMailSubjectQualificationRenewal $ qualShort l + getMailBody l@LetterRenewQualificationF{..} = Just $ \DateTimeFormatter{ format } -> + let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l + in $(ihamletFile "templates/mail/body/qualificationRenewal.hamlet") letterMeta l@LetterRenewQualificationF{..} DateTimeFormatter{ format } lang Entity{entityKey=rcvrId, entityVal=User{userDisplayName}} = let LetterRenewQualificationFData{..} = letterRenewalQualificationFData l @@ -67,6 +67,9 @@ instance MDLetter LetterRenewQualificationF where , toMeta "de-opening" ("Sehr geehrte Damen und Herren,"::Text) , toMeta "en-opening" ("Dear Sir or Madam,"::Text) ] <> + guardMonoid isReminder + [ toMeta "reminder" ("reminder"::Text) + ] <> [ toMeta "lang" lang , toMeta "login" lmsIdent , toMeta "pin" lmsPin @@ -75,11 +78,12 @@ instance MDLetter LetterRenewQualificationF where , mbMeta "validduration" (show <$> qualDuration) , toMeta "url-text" lmsUrl , toMeta "url" lmsUrlLogin + ] getPJId LetterRenewQualificationF{..} = PrintJobIdentification - { pjiName = "Renewal" + { pjiName = bool "Renewal" "Renewal Reminder" isReminder , pjiApcAcknowledge = "lms-" <> getLmsIdent lmsLogin , pjiRecipient = Nothing -- to be filled later , pjiSender = Nothing diff --git a/src/Utils/Print/SomeLetter.hs b/src/Utils/Print/SomeLetter.hs index b10ed63c0..e0ba66645 100644 --- a/src/Utils/Print/SomeLetter.hs +++ b/src/Utils/Print/SomeLetter.hs @@ -8,11 +8,7 @@ module Utils.Print.SomeLetter where import Utils.Print.Letters -data SomeLetter = forall l . (MDLetter l, MDMail l) => SomeLetter l -- a record selector would be useless here due to the escaped type variable - -instance MDMail SomeLetter where - getMailSubject (SomeLetter l) = getMailSubject l - getMailBody (SomeLetter l) = getMailBody l +data SomeLetter = forall l . (MDLetter l) => SomeLetter l -- a record selector would be useless here due to the escaped type variable instance MDLetter SomeLetter where letterMeta (SomeLetter l) = letterMeta l @@ -20,4 +16,6 @@ instance MDLetter SomeLetter where getLetterEnvelope (SomeLetter l) = getLetterEnvelope l getLetterKind (SomeLetter l) = getLetterKind l getTemplate (SomeLetter l) = getTemplate l + getMailSubject (SomeLetter l) = getMailSubject l + getMailBody (SomeLetter l) = getMailBody l encryptPDFfor (SomeLetter l) = encryptPDFfor l \ No newline at end of file diff --git a/src/Utils/TH.hs b/src/Utils/TH.hs index 189d78b45..40669cc2f 100644 --- a/src/Utils/TH.hs +++ b/src/Utils/TH.hs @@ -35,7 +35,7 @@ import Utils.PathPiece -- Alternatively uses lenses: "^. _3" projects the 3rd component of an n-tuple for any n >=3, requires import Control.Lens projNI :: Int -> Int -> ExpQ -- generic projection gives I-th element of N-tuple, i.e. snd3 = $(projNI 3 2) --ghci -fth --- $(projN n m) :: (t1,..,tn) -> tm (for m<=n) +-- Usage like so: $(projN n m) :: (t1,..,tn) -> tm (for m<=n) projNI n i = do x <- newName "x" let rhs = varE x diff --git a/templates/i18n/applications-list-info/de-de-formal.hamlet b/templates/i18n/applications-list-info/de-de-formal.hamlet index a868a785f..c48534e00 100644 --- a/templates/i18n/applications-list-info/de-de-formal.hamlet +++ b/templates/i18n/applications-list-info/de-de-formal.hamlet @@ -15,8 +15,8 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later

Widersprechen Sie daher bitte nicht aufgrund der Studiendaten, oder # - weil Studiendaten fehlen, der Zuteilung eines Studierenden zu Ihrem # - Kurs (Veto bzw. 5.0). + weil Studiendaten fehlen, der Zuteilung eines Lernenden zu Ihrem # + Kursart (Veto bzw. 5.0).

diff --git a/templates/i18n/course-exam-office-explanation/de-de-formal.hamlet b/templates/i18n/course-exam-office-explanation/de-de-formal.hamlet index 9a9908c13..71f0c10fc 100644 --- a/templates/i18n/course-exam-office-explanation/de-de-formal.hamlet +++ b/templates/i18n/course-exam-office-explanation/de-de-formal.hamlet @@ -6,7 +6,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later

Hier können Sie der Meldung ihrer Prüfungsleistungen an Prüfungsverwalter:innen # - bestimmter Institute (innerhalb von Uni2work) widersprechen. + bestimmter Bereiche (innerhalb von Uni2work) widersprechen.

Bedenken Sie, dass die Meldung der Prüfungsleistungen direkt in Uni2work den # Verwaltungsaufwand (und die damit verbunden Dauer) für die ordnungsgemäße # @@ -14,7 +14,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later

Unter Umständen können Prüfungsverwalter:innen ungeachtet der Angaben, die Sie hier # machen, Einsicht in Ihre Leistungen erlangen.
- Dies geschieht nur in begründeten Einzelfällen (z.B. bei Studierenden im # + Dies geschieht nur in begründeten Einzelfällen (z.B. bei Lernenden im # ERASMUS-Programm).

Nutzer:innen, die unabhängig von diesen Einstellungen, Einsicht in Ihre # diff --git a/templates/i18n/data-delete/en-eu.hamlet b/templates/i18n/data-delete/en-eu.hamlet index 5b7a5fdb4..b374682eb 100644 --- a/templates/i18n/data-delete/en-eu.hamlet +++ b/templates/i18n/data-delete/en-eu.hamlet @@ -22,7 +22,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later

Caution: Exercise submissions are deleted as well! - If a lecturer has not backed up the information regarding submissions + If a course administrator has not backed up the information regarding submissions elsewhere this is expected to result in a loss of exercise bonus. Grades synchronised externally should not be impacted by this but may not be able to be reconstructed without the information of Uni2work-managed diff --git a/templates/i18n/exam-correct-explanation/de-de-formal.hamlet b/templates/i18n/exam-correct-explanation/de-de-formal.hamlet index b03df95a5..740bd26eb 100644 --- a/templates/i18n/exam-correct-explanation/de-de-formal.hamlet +++ b/templates/i18n/exam-correct-explanation/de-de-formal.hamlet @@ -9,7 +9,7 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later Teilnehmer-Spalte einen beliebigen eindeutigen Identifikator des # Teilnehmers/der Teilnehmerin angeben.
- Es können nur Ergebnisse für Studierende eingetragen werden, die # + Es können nur Ergebnisse für Lernende eingetragen werden, die # bereits Prüfungsteilnehmer:in sind. # Über diese Oberfläche können keine neuen Benutzer zur Klausur # angemeldet werden.
diff --git a/templates/i18n/faq/course-correctors-tutors.de-de-formal.hamlet b/templates/i18n/faq/course-correctors-tutors.de-de-formal.hamlet index 38f1956f3..0c68818a5 100644 --- a/templates/i18n/faq/course-correctors-tutors.de-de-formal.hamlet +++ b/templates/i18n/faq/course-correctors-tutors.de-de-formal.hamlet @@ -5,6 +5,6 @@ $# $# SPDX-License-Identifier: AGPL-3.0-or-later

- Tutor:innen und Korrektor:innen werden beim Anlegen oder Editieren des # - jeweiligen Tutoriums bzw. Übungsblattes angegeben. + Ausbilder:innen und Korrektor:innen werden beim Anlegen oder Editieren des # + jeweiligen Kurses bzw. Übungsblattes angegeben. diff --git a/templates/i18n/faq/course-correctors-tutors.en-eu.hamlet b/templates/i18n/faq/course-correctors-tutors.en-eu.hamlet index f0700bca9..f4fe7f813 100644 --- a/templates/i18n/faq/course-correctors-tutors.en-eu.hamlet +++ b/templates/i18n/faq/course-correctors-tutors.en-eu.hamlet @@ -5,5 +5,5 @@ $# $# SPDX-License-Identifier: AGPL-3.0-or-later

- Tutors and correctors are assigned when creating or editing the # - respective tutorial or exercise sheet. + Instructors and correctors are assigned when creating or editing the # + respective course or exercise sheet. diff --git a/templates/i18n/faq/no-campus-account.de-de-formal.hamlet b/templates/i18n/faq/no-campus-account.de-de-formal.hamlet index c83e3396d..6e48b4536 100644 --- a/templates/i18n/faq/no-campus-account.de-de-formal.hamlet +++ b/templates/i18n/faq/no-campus-account.de-de-formal.hamlet @@ -5,23 +5,22 @@ $# $# SPDX-License-Identifier: AGPL-3.0-or-later

- Uni2work-Administrator:innen können Uni2work-interne Kennungen ausstellen. + FRADrive-Administrator:innen können interne Kennungen ausstellen.

Wenden Sie sich dafür über das Hilfe-Formular, # - oben rechts auf jeder Seite, an die Uni2work-Administration. + oben rechts auf jeder Seite, an die FRADrive-Administration.

Beschreiben Sie dabei bitte Ihre Situation und begründen Sie, warum # Sie Zugriff auf das System benötigen.

- Um einen Uni2work-internen Account zu erstellen werden folgende # + Um einen FRADrive-internen Account zu erstellen werden folgende # Informationen benötigt, senden Sie diese bitte direkt mit Ihrer # Anfrage: -

-
Akademischer Titel +
Vorname(n)
Vollständiger Nachname
Der Nachname kann aus mehreren Wörtern bestehen @@ -30,18 +29,14 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later
Der vollständige Name muss mindestens den kompletten Nachnamen enthalten
Der vollständige Name kann zudem beliebige Teile der Vornamen und des akademischen Titels enthalten
So wird der Name anderen Benutzer:innen angezeigt -
Matrikelnummer -
Auch jene einer externen Institution (z.B. TUM) -
Geschlecht -
„Unbekannt“, „Männlich“, „Weiblich“ oder „Keine Angabe“ -$#
Nach ISO 5218 +
AVS Nummer +
Alternativ kann auch die Kartennummer des Flughafenausweises inklusive Punkt und Zahl danach angegeben werden +
E-Mail Adresse zum Versand +
An diese Adresse werden Mitteilungen von FRADrive versandt +
Die zuverlässige Zustellung muss gewährleistet sein, daher keine Emails von freien Mailanbietern wie GMail, Hotmail, GMX, etc.
E-Mail Adresse zur Anzeige
Wird öffentlich angezeigt, wenn man z.B. als Kursverwalter:innen oder Korrektor:innen eingetragen ist -
Kursverwalter von Kursen, in denen man Teilnehmer:in ist, sehen die E-Mail Adresse zum Versand -
E-Mail Adresse zum Versand -
An diese Adresse werden Mitteilungen von Uni2work versandt -
Die zuverlässige Zustellung muss gewährleistet sein, daher keine Emails von freien Mailanbietern wie GMail, Hotmail, GMX, etc. -
Bei externen Studierenden sollte die E-Mail Adresse der externen Institution verwendet werden, z.B. @mytum.de für TUM-Studierende +
Kursverwalter von Kursarten, in denen man Teilnehmer:in ist, sehen diese E-Mail Adresse zum Versand

Nach Bearbeitung Ihres Anliegens erhalten Sie eine E-Mail, die Sie # diff --git a/templates/i18n/faq/no-campus-account.en-eu.hamlet b/templates/i18n/faq/no-campus-account.en-eu.hamlet index 879521915..404e6b566 100644 --- a/templates/i18n/faq/no-campus-account.en-eu.hamlet +++ b/templates/i18n/faq/no-campus-account.en-eu.hamlet @@ -4,42 +4,37 @@ $# SPDX-FileCopyrightText: 2022 Gregor Kleen ,Sarah Vau $# $# SPDX-License-Identifier: AGPL-3.0-or-later -

- - Uni2work-administrators can create Uni2work-internal accounts. +

+ FRADrive-administrators mayn create internal accounts.

Please use the Support form (at the top right # - of every page) to contact a Uni2work-administrator. + of every page) to contact a FRADrive-administrator.

Explain your situation and provide a reason for requiring access to # - Uni2work. + FRADrive.

Please send the following information with your request:

-
Academic title
Given name(s)
Full surname
The surname may consist of multiple words.
Full name
The full name must contain the complete surname.
The full name may also contain arbitrary components of the given name(s) and academic title. -
Matriculation number -
Matriculations of external instutions (e.g. TUM) are also accepted. -
Sex -
“Not known”, “Male”, “Female”, or “Not specified” -
Email address for display -
This email address is published if you are for example a course administrator or corrector. -
Course administrators for courses in which you participate are shown the email address for sending. +
AVS number +
Alternatively provide the card number of your airport id card, including the number after the dot.
Email address for sending -
Uni2work sends notifications to this address. +
FRADrive sends notifications to this address, maybe identical to Email address for display.
Reliable delivery of email must be ensured. Therefore free mail hosters like GMail, Hotmail, GMX, etc. are not permitted. -
For external students the email address provided by their institution should be used, e.g. @mytum.de for TUM-students. - +
Email address for display +
This email address is published if you are for example a course administrator or instructor. +
Course administrators for courses in which you participate are shown the email address for sending. +

After your request has been processed you will receive an email # asking you to set a password to login. diff --git a/templates/i18n/faq/not-lecturer-how-to-create-courses.de-de-formal.hamlet b/templates/i18n/faq/not-lecturer-how-to-create-courses.de-de-formal.hamlet index 705c9c44c..d56479225 100644 --- a/templates/i18n/faq/not-lecturer-how-to-create-courses.de-de-formal.hamlet +++ b/templates/i18n/faq/not-lecturer-how-to-create-courses.de-de-formal.hamlet @@ -5,7 +5,7 @@ $# $# SPDX-License-Identifier: AGPL-3.0-or-later

- Die Berechtigung neue Kurse anzulegen wird manuell eingeräumt. + Die Berechtigung neue Kursarten anzulegen wird manuell eingeräumt.
Wenden Sie sich dafür über das Hilfe-Formular, # oben rechts auf jeder Seite, an die Uni2work-Administration. diff --git a/templates/i18n/featureList/en-eu.hamlet b/templates/i18n/featureList/en-eu.hamlet index 6117cec67..7ee05d757 100644 --- a/templates/i18n/featureList/en-eu.hamlet +++ b/templates/i18n/featureList/en-eu.hamlet @@ -9,4 +9,4 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later Planned functionally, currently only partially implemented