From 7981371136e242dc7b30c08f4e2668d1ac3441d6 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Wed, 13 May 2026 10:57:23 +0200 Subject: [PATCH] feat(TrainingCancellation): enhance cancellation functionality and localization support - Updated the training cancellation controller to accept training group IDs, improving the cancellation process. - Modified the database schema to include a JSON field for training group IDs in the training cancellations table. - Enhanced the TrainingCancellation model to support the new training group IDs field. - Updated the training cancellation service to normalize and handle training group IDs effectively. - Added localization support for training cancellation features across multiple languages, improving user experience. --- .../trainingCancellationController.js | 5 +- ...ng_group_ids_to_training_cancellations.sql | 2 + .../create_training_cancellations_table.sql | 1 + backend/models/TrainingCancellation.js | 5 + .../services/trainingCancellationService.js | 28 +- frontend/src/i18n/locales/de-CH.json | 100 +++ frontend/src/i18n/locales/de-extended.json | 100 +++ frontend/src/i18n/locales/de.json | 100 +++ frontend/src/i18n/locales/en-AU.json | 100 +++ frontend/src/i18n/locales/en-GB.json | 100 +++ frontend/src/i18n/locales/en-US.json | 100 +++ frontend/src/i18n/locales/es.json | 100 +++ frontend/src/i18n/locales/fil.json | 100 +++ frontend/src/i18n/locales/fr.json | 100 +++ frontend/src/i18n/locales/it.json | 100 +++ frontend/src/i18n/locales/ja.json | 100 +++ frontend/src/i18n/locales/pl.json | 100 +++ frontend/src/i18n/locales/th.json | 100 +++ frontend/src/i18n/locales/tl.json | 100 +++ frontend/src/i18n/locales/zh.json | 100 +++ frontend/src/views/CalendarView.vue | 575 +++++++++++++----- .../kotlin/de/tt_tagebuch/app/ui/AppRoot.kt | 465 ++++++++++---- 22 files changed, 2306 insertions(+), 275 deletions(-) create mode 100644 backend/migrations/add_training_group_ids_to_training_cancellations.sql diff --git a/backend/controllers/trainingCancellationController.js b/backend/controllers/trainingCancellationController.js index b154b116..d86be40c 100644 --- a/backend/controllers/trainingCancellationController.js +++ b/backend/controllers/trainingCancellationController.js @@ -19,13 +19,14 @@ export const upsertTrainingCancellation = async (req, res) => { try { const { authcode: userToken } = req.headers; const { clubId } = req.params; - const { date, startDate, endDate, reason } = req.body; + const { date, startDate, endDate, reason, trainingGroupIds } = req.body; const result = await trainingCancellationService.upsertTrainingCancellation( userToken, clubId, startDate || date, reason, - endDate || date || startDate + endDate || date || startDate, + trainingGroupIds ); res.status(200).json(result); } catch (error) { diff --git a/backend/migrations/add_training_group_ids_to_training_cancellations.sql b/backend/migrations/add_training_group_ids_to_training_cancellations.sql new file mode 100644 index 00000000..8385d8c8 --- /dev/null +++ b/backend/migrations/add_training_group_ids_to_training_cancellations.sql @@ -0,0 +1,2 @@ +ALTER TABLE training_cancellations + ADD COLUMN IF NOT EXISTS training_group_ids JSON NULL; diff --git a/backend/migrations/create_training_cancellations_table.sql b/backend/migrations/create_training_cancellations_table.sql index bfb90e4e..d444e8ad 100644 --- a/backend/migrations/create_training_cancellations_table.sql +++ b/backend/migrations/create_training_cancellations_table.sql @@ -5,6 +5,7 @@ CREATE TABLE IF NOT EXISTS training_cancellations ( end_date DATE NOT NULL, date DATE NULL, reason VARCHAR(255) NULL, + training_group_ids JSON NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uniq_training_cancellation_club_range (club_id, start_date, end_date), diff --git a/backend/models/TrainingCancellation.js b/backend/models/TrainingCancellation.js index 1cc9b89c..a53b2c64 100644 --- a/backend/models/TrainingCancellation.js +++ b/backend/models/TrainingCancellation.js @@ -36,6 +36,11 @@ const TrainingCancellation = sequelize.define('TrainingCancellation', { type: DataTypes.STRING(255), allowNull: true, }, + trainingGroupIds: { + type: DataTypes.JSON, + allowNull: true, + field: 'training_group_ids', + }, }, { tableName: 'training_cancellations', underscored: true, diff --git a/backend/services/trainingCancellationService.js b/backend/services/trainingCancellationService.js index e1cf3dba..92b3e003 100644 --- a/backend/services/trainingCancellationService.js +++ b/backend/services/trainingCancellationService.js @@ -24,10 +24,11 @@ class TrainingCancellationService { }); } - async upsertTrainingCancellation(userToken, clubId, date, reason, endDate = null) { + async upsertTrainingCancellation(userToken, clubId, date, reason, endDate = null, trainingGroupIds = []) { await checkAccess(userToken, clubId); const normalizedStartDate = this.normalizeDate(date); const normalizedEndDate = this.normalizeDate(endDate || date); + const normalizedTrainingGroupIds = this.normalizeTrainingGroupIds(trainingGroupIds); if (!normalizedStartDate || !normalizedEndDate) { throw new HttpError('Ungültiges Datum', 400); } @@ -41,6 +42,7 @@ class TrainingCancellationService { endDate: normalizedEndDate, date: normalizedStartDate, reason: String(reason || '').trim() || null, + trainingGroupIds: normalizedTrainingGroupIds, }); return cancellation || await TrainingCancellation.findOne({ where: { clubId, startDate: normalizedStartDate, endDate: normalizedEndDate }, @@ -71,6 +73,30 @@ class TrainingCancellationService { const text = String(date || '').slice(0, 10); return /^\d{4}-\d{2}-\d{2}$/.test(text) ? text : null; } + + normalizeTrainingGroupIds(trainingGroupIds) { + const values = this.parseTrainingGroupIdsValue(trainingGroupIds); + return [...new Set( + values + .map(id => Number.parseInt(id, 10)) + .filter(id => Number.isInteger(id) && id > 0) + )]; + } + + parseTrainingGroupIdsValue(trainingGroupIds) { + if (Array.isArray(trainingGroupIds)) return trainingGroupIds; + if (trainingGroupIds === null || trainingGroupIds === undefined || trainingGroupIds === '') return []; + if (typeof trainingGroupIds === 'string') { + try { + const parsed = JSON.parse(trainingGroupIds); + if (Array.isArray(parsed)) return parsed; + if (parsed !== null && parsed !== undefined) return [parsed]; + } catch (error) { + return trainingGroupIds.split(','); + } + } + return []; + } } export default new TrainingCancellationService(); diff --git a/frontend/src/i18n/locales/de-CH.json b/frontend/src/i18n/locales/de-CH.json index 695eaa0f..6bab6c70 100644 --- a/frontend/src/i18n/locales/de-CH.json +++ b/frontend/src/i18n/locales/de-CH.json @@ -62,6 +62,106 @@ "ok": "OK", "saving": "Speichere..." }, + "calendar": { + "eyebrow": "Vereinskalender", + "title": "Kalender", + "description": "Trainingstage, Vereinsturniere und Punktspiele in einer Monatsansicht.", + "today": "Heute", + "loading": "Kalenderdaten werden geladen...", + "noClub": "Bitte zuerst einen Verein auswählen.", + "loadError": "Kalenderdaten konnten nicht geladen werden.", + "sourceWarning": "{source} konnte nicht geladen werden", + "agendaTitle": "Termine im Monat", + "agendaEmpty": "Keine Termine in diesem Monat.", + "recurringTrainingTime": "Regelmäßige Trainingszeit", + "participants": "{count} Teilnehmer", + "starts": "{count} Starts", + "options": { + "title": "Optionen", + "subtitle": "Ausfälle & eigene Termine" + }, + "legend": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Teilnahme", + "match": "Punktspiel", + "holiday": "Feiertag", + "schoolHoliday": "Ferien", + "trainingCancellation": "Ausfall", + "customEvent": "Termin" + }, + "cancellation": { + "title": "Training fällt aus", + "description": "Blendet regelmäßige Trainingszeiten aus.", + "date": "Datum", + "untilOptional": "Bis optional", + "trainingGroups": "Trainingsgruppen", + "reasonPlaceholder": "Grund (optional)", + "saving": "Speichern...", + "submit": "Eintragen", + "fallbackTitle": "Training fällt aus", + "subtitle": "Trainingsausfall" + }, + "customEvent": { + "title": "Eigene Termine", + "description": "Kreistage, Sitzungen, interne Meetings, ...", + "titlePlaceholder": "Titel", + "categoryPlaceholder": "Kategorie (optional)", + "saving": "Speichern...", + "submit": "Anlegen", + "subtitleFallback": "Eigener Termin" + }, + "quickCancellation": { + "title": "Trainingsausfall", + "message": "„{title}“ als Trainingsausfall markieren?", + "useWholeRange": "Für den gesamten Zeitraum ({start} bis {end}) eintragen", + "trainingGroups": "Betroffene Trainingsgruppen", + "confirm": "Ausfall eintragen", + "noGroups": "Es sind keine Trainingsgruppen mit Trainingszeiten vorhanden." + }, + "sources": { + "trainingDays": "Trainingstage", + "trainingTimes": "Trainingszeiten", + "trainingCancellations": "Trainingsausfälle", + "customEvents": "Eigene Termine", + "tournaments": "Turniere", + "officialTournaments": "Turnierteilnahmen", + "matches": "Punktspiele", + "holidays": "Ferien/Feiertage" + }, + "eventTitles": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Turnierteilnahme", + "match": "Punktspiel" + }, + "tournament": { + "open": "Offenes Turnier", + "club": "Vereinsturnier" + }, + "match": { + "home": "Heim", + "guest": "Gast" + }, + "holidayTypes": { + "holiday": "Feiertag", + "schoolHoliday": "Schulferien" + }, + "weekdays": { + "monday": "Mo", + "tuesday": "Di", + "wednesday": "Mi", + "thursday": "Do", + "friday": "Fr", + "saturday": "Sa", + "sunday": "So" + }, + "cancelCancellation": { + "title": "Trainingsausfall stornieren", + "message": "Trainingsausfall „{title}“ am {date} wirklich stornieren?", + "confirm": "Ausfall stornieren" + } + }, "unknown": "Unbekannt", "navigation": { "home": "Startseite", diff --git a/frontend/src/i18n/locales/de-extended.json b/frontend/src/i18n/locales/de-extended.json index 53d6acbb..49b94ac4 100644 --- a/frontend/src/i18n/locales/de-extended.json +++ b/frontend/src/i18n/locales/de-extended.json @@ -62,6 +62,106 @@ "period": "Zeitraum", "saving": "Speichere..." }, + "calendar": { + "eyebrow": "Vereinskalender", + "title": "Kalender", + "description": "Trainingstage, Vereinsturniere und Punktspiele in einer Monatsansicht.", + "today": "Heute", + "loading": "Kalenderdaten werden geladen...", + "noClub": "Bitte zuerst einen Verein auswählen.", + "loadError": "Kalenderdaten konnten nicht geladen werden.", + "sourceWarning": "{source} konnte nicht geladen werden", + "agendaTitle": "Termine im Monat", + "agendaEmpty": "Keine Termine in diesem Monat.", + "recurringTrainingTime": "Regelmäßige Trainingszeit", + "participants": "{count} Teilnehmer", + "starts": "{count} Starts", + "options": { + "title": "Optionen", + "subtitle": "Ausfälle & eigene Termine" + }, + "legend": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Teilnahme", + "match": "Punktspiel", + "holiday": "Feiertag", + "schoolHoliday": "Ferien", + "trainingCancellation": "Ausfall", + "customEvent": "Termin" + }, + "cancellation": { + "title": "Training fällt aus", + "description": "Blendet regelmäßige Trainingszeiten aus.", + "date": "Datum", + "untilOptional": "Bis optional", + "trainingGroups": "Trainingsgruppen", + "reasonPlaceholder": "Grund (optional)", + "saving": "Speichern...", + "submit": "Eintragen", + "fallbackTitle": "Training fällt aus", + "subtitle": "Trainingsausfall" + }, + "customEvent": { + "title": "Eigene Termine", + "description": "Kreistage, Sitzungen, interne Meetings, ...", + "titlePlaceholder": "Titel", + "categoryPlaceholder": "Kategorie (optional)", + "saving": "Speichern...", + "submit": "Anlegen", + "subtitleFallback": "Eigener Termin" + }, + "quickCancellation": { + "title": "Trainingsausfall", + "message": "„{title}“ als Trainingsausfall markieren?", + "useWholeRange": "Für den gesamten Zeitraum ({start} bis {end}) eintragen", + "trainingGroups": "Betroffene Trainingsgruppen", + "confirm": "Ausfall eintragen", + "noGroups": "Es sind keine Trainingsgruppen mit Trainingszeiten vorhanden." + }, + "sources": { + "trainingDays": "Trainingstage", + "trainingTimes": "Trainingszeiten", + "trainingCancellations": "Trainingsausfälle", + "customEvents": "Eigene Termine", + "tournaments": "Turniere", + "officialTournaments": "Turnierteilnahmen", + "matches": "Punktspiele", + "holidays": "Ferien/Feiertage" + }, + "eventTitles": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Turnierteilnahme", + "match": "Punktspiel" + }, + "tournament": { + "open": "Offenes Turnier", + "club": "Vereinsturnier" + }, + "match": { + "home": "Heim", + "guest": "Gast" + }, + "holidayTypes": { + "holiday": "Feiertag", + "schoolHoliday": "Schulferien" + }, + "weekdays": { + "monday": "Mo", + "tuesday": "Di", + "wednesday": "Mi", + "thursday": "Do", + "friday": "Fr", + "saturday": "Sa", + "sunday": "So" + }, + "cancelCancellation": { + "title": "Trainingsausfall stornieren", + "message": "Trainingsausfall „{title}“ am {date} wirklich stornieren?", + "confirm": "Ausfall stornieren" + } + }, "unknown": "Unbekannt", "navigation": { "home": "Startseite", diff --git a/frontend/src/i18n/locales/de.json b/frontend/src/i18n/locales/de.json index 9d369cd3..eec5012d 100644 --- a/frontend/src/i18n/locales/de.json +++ b/frontend/src/i18n/locales/de.json @@ -62,6 +62,106 @@ "period": "Zeitraum", "saving": "Speichere..." }, + "calendar": { + "eyebrow": "Vereinskalender", + "title": "Kalender", + "description": "Trainingstage, Vereinsturniere und Punktspiele in einer Monatsansicht.", + "today": "Heute", + "loading": "Kalenderdaten werden geladen...", + "noClub": "Bitte zuerst einen Verein auswählen.", + "loadError": "Kalenderdaten konnten nicht geladen werden.", + "sourceWarning": "{source} konnte nicht geladen werden", + "agendaTitle": "Termine im Monat", + "agendaEmpty": "Keine Termine in diesem Monat.", + "recurringTrainingTime": "Regelmäßige Trainingszeit", + "participants": "{count} Teilnehmer", + "starts": "{count} Starts", + "options": { + "title": "Optionen", + "subtitle": "Ausfälle & eigene Termine" + }, + "legend": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Teilnahme", + "match": "Punktspiel", + "holiday": "Feiertag", + "schoolHoliday": "Ferien", + "trainingCancellation": "Ausfall", + "customEvent": "Termin" + }, + "cancellation": { + "title": "Training fällt aus", + "description": "Blendet regelmäßige Trainingszeiten aus.", + "date": "Datum", + "untilOptional": "Bis optional", + "trainingGroups": "Trainingsgruppen", + "reasonPlaceholder": "Grund (optional)", + "saving": "Speichern...", + "submit": "Eintragen", + "fallbackTitle": "Training fällt aus", + "subtitle": "Trainingsausfall" + }, + "customEvent": { + "title": "Eigene Termine", + "description": "Kreistage, Sitzungen, interne Meetings, ...", + "titlePlaceholder": "Titel", + "categoryPlaceholder": "Kategorie (optional)", + "saving": "Speichern...", + "submit": "Anlegen", + "subtitleFallback": "Eigener Termin" + }, + "quickCancellation": { + "title": "Trainingsausfall", + "message": "„{title}“ als Trainingsausfall markieren?", + "useWholeRange": "Für den gesamten Zeitraum ({start} bis {end}) eintragen", + "trainingGroups": "Betroffene Trainingsgruppen", + "confirm": "Ausfall eintragen", + "noGroups": "Es sind keine Trainingsgruppen mit Trainingszeiten vorhanden." + }, + "sources": { + "trainingDays": "Trainingstage", + "trainingTimes": "Trainingszeiten", + "trainingCancellations": "Trainingsausfälle", + "customEvents": "Eigene Termine", + "tournaments": "Turniere", + "officialTournaments": "Turnierteilnahmen", + "matches": "Punktspiele", + "holidays": "Ferien/Feiertage" + }, + "eventTitles": { + "training": "Training", + "tournament": "Turnier", + "officialTournament": "Turnierteilnahme", + "match": "Punktspiel" + }, + "tournament": { + "open": "Offenes Turnier", + "club": "Vereinsturnier" + }, + "match": { + "home": "Heim", + "guest": "Gast" + }, + "holidayTypes": { + "holiday": "Feiertag", + "schoolHoliday": "Schulferien" + }, + "weekdays": { + "monday": "Mo", + "tuesday": "Di", + "wednesday": "Mi", + "thursday": "Do", + "friday": "Fr", + "saturday": "Sa", + "sunday": "So" + }, + "cancelCancellation": { + "title": "Trainingsausfall stornieren", + "message": "Trainingsausfall „{title}“ am {date} wirklich stornieren?", + "confirm": "Ausfall stornieren" + } + }, "unknown": "Unbekannt", "navigation": { "home": "Startseite", diff --git a/frontend/src/i18n/locales/en-AU.json b/frontend/src/i18n/locales/en-AU.json index a643c17b..5f85b76f 100644 --- a/frontend/src/i18n/locales/en-AU.json +++ b/frontend/src/i18n/locales/en-AU.json @@ -62,6 +62,106 @@ "years": "years", "ok": "OK" }, + "calendar": { + "eyebrow": "Club calendar", + "title": "Calendar", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Today", + "loading": "Loading calendar data...", + "noClub": "Please select a club first.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Events this month", + "agendaEmpty": "No events this month.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Mon", + "tuesday": "Tue", + "wednesday": "Wed", + "thursday": "Thu", + "friday": "Fri", + "saturday": "Sat", + "sunday": "Sun" + }, + "cancelCancellation": { + "title": "Cancel training cancellation", + "message": "Really cancel the training cancellation “{title}” on {date}?", + "confirm": "Cancel cancellation" + } + }, "navigation": { "home": "Home", "members": "Members", diff --git a/frontend/src/i18n/locales/en-GB.json b/frontend/src/i18n/locales/en-GB.json index 4ea7073a..06f96b3e 100644 --- a/frontend/src/i18n/locales/en-GB.json +++ b/frontend/src/i18n/locales/en-GB.json @@ -62,6 +62,106 @@ "years": "years", "ok": "OK" }, + "calendar": { + "eyebrow": "Club calendar", + "title": "Calendar", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Today", + "loading": "Loading calendar data...", + "noClub": "Please select a club first.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Events this month", + "agendaEmpty": "No events this month.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Mon", + "tuesday": "Tue", + "wednesday": "Wed", + "thursday": "Thu", + "friday": "Fri", + "saturday": "Sat", + "sunday": "Sun" + }, + "cancelCancellation": { + "title": "Cancel training cancellation", + "message": "Really cancel the training cancellation “{title}” on {date}?", + "confirm": "Cancel cancellation" + } + }, "navigation": { "home": "Home", "members": "Members", diff --git a/frontend/src/i18n/locales/en-US.json b/frontend/src/i18n/locales/en-US.json index 60a1e446..95102ec3 100644 --- a/frontend/src/i18n/locales/en-US.json +++ b/frontend/src/i18n/locales/en-US.json @@ -62,6 +62,106 @@ "years": "years", "ok": "OK" }, + "calendar": { + "eyebrow": "Club calendar", + "title": "Calendar", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Today", + "loading": "Loading calendar data...", + "noClub": "Please select a club first.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Events this month", + "agendaEmpty": "No events this month.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Mon", + "tuesday": "Tue", + "wednesday": "Wed", + "thursday": "Thu", + "friday": "Fri", + "saturday": "Sat", + "sunday": "Sun" + }, + "cancelCancellation": { + "title": "Cancel training cancellation", + "message": "Really cancel the training cancellation “{title}” on {date}?", + "confirm": "Cancel cancellation" + } + }, "navigation": { "home": "Home", "members": "Members", diff --git a/frontend/src/i18n/locales/es.json b/frontend/src/i18n/locales/es.json index d43b4f90..3d20b8a6 100644 --- a/frontend/src/i18n/locales/es.json +++ b/frontend/src/i18n/locales/es.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Periodo" }, + "calendar": { + "eyebrow": "Calendario del club", + "title": "Calendario", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Hoy", + "loading": "Cargando datos del calendario...", + "noClub": "Seleccione primero un club.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Eventos del mes", + "agendaEmpty": "No hay eventos este mes.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Lun", + "tuesday": "Mar", + "wednesday": "Mié", + "thursday": "Jue", + "friday": "Vie", + "saturday": "Sáb", + "sunday": "Dom" + }, + "cancelCancellation": { + "title": "Cancelar ausencia de entrenamiento", + "message": "¿Cancelar realmente la ausencia “{title}” el {date}?", + "confirm": "Cancelar ausencia" + } + }, "navigation": { "home": "Inicio", "members": "Miembros", diff --git a/frontend/src/i18n/locales/fil.json b/frontend/src/i18n/locales/fil.json index 5a33e101..6df2d35a 100644 --- a/frontend/src/i18n/locales/fil.json +++ b/frontend/src/i18n/locales/fil.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Panahon" }, + "calendar": { + "eyebrow": "Kalendaryo ng club", + "title": "Kalendaryo", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Ngayon", + "loading": "Nilo-load ang datos ng kalendaryo...", + "noClub": "Pumili muna ng club.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Mga event ngayong buwan", + "agendaEmpty": "Walang event ngayong buwan.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Lun", + "tuesday": "Mar", + "wednesday": "Miy", + "thursday": "Huw", + "friday": "Biy", + "saturday": "Sab", + "sunday": "Lin" + }, + "cancelCancellation": { + "title": "Bawiin ang pagkansela ng training", + "message": "Bawiin talaga ang pagkansela ng training “{title}” sa {date}?", + "confirm": "Bawiin ang pagkansela" + } + }, "navigation": { "home": "Home", "members": "Mga miyembro", diff --git a/frontend/src/i18n/locales/fr.json b/frontend/src/i18n/locales/fr.json index 28e0913f..536a26bf 100644 --- a/frontend/src/i18n/locales/fr.json +++ b/frontend/src/i18n/locales/fr.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Période" }, + "calendar": { + "eyebrow": "Calendrier du club", + "title": "Calendrier", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Aujourd’hui", + "loading": "Chargement des données du calendrier...", + "noClub": "Veuillez d’abord sélectionner un club.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Événements du mois", + "agendaEmpty": "Aucun événement ce mois-ci.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Lun", + "tuesday": "Mar", + "wednesday": "Mer", + "thursday": "Jeu", + "friday": "Ven", + "saturday": "Sam", + "sunday": "Dim" + }, + "cancelCancellation": { + "title": "Annuler l’annulation de l’entraînement", + "message": "Vraiment annuler l’annulation « {title} » le {date} ?", + "confirm": "Annuler l’annulation" + } + }, "navigation": { "home": "Accueil", "members": "Membres", diff --git a/frontend/src/i18n/locales/it.json b/frontend/src/i18n/locales/it.json index e135a736..8790e1fc 100644 --- a/frontend/src/i18n/locales/it.json +++ b/frontend/src/i18n/locales/it.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Periodo" }, + "calendar": { + "eyebrow": "Calendario del club", + "title": "Calendario", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Oggi", + "loading": "Caricamento dati calendario...", + "noClub": "Seleziona prima un club.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Eventi del mese", + "agendaEmpty": "Nessun evento questo mese.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Lun", + "tuesday": "Mar", + "wednesday": "Mer", + "thursday": "Gio", + "friday": "Ven", + "saturday": "Sab", + "sunday": "Dom" + }, + "cancelCancellation": { + "title": "Annulla cancellazione allenamento", + "message": "Annullare davvero la cancellazione “{title}” del {date}?", + "confirm": "Annulla cancellazione" + } + }, "navigation": { "home": "Home", "members": "Membri", diff --git a/frontend/src/i18n/locales/ja.json b/frontend/src/i18n/locales/ja.json index 012dccc3..6ef0e18a 100644 --- a/frontend/src/i18n/locales/ja.json +++ b/frontend/src/i18n/locales/ja.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "期間" }, + "calendar": { + "eyebrow": "クラブカレンダー", + "title": "カレンダー", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "今日", + "loading": "カレンダーデータを読み込んでいます...", + "noClub": "最初にクラブを選択してください。", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "今月の予定", + "agendaEmpty": "今月の予定はありません。", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "月", + "tuesday": "火", + "wednesday": "水", + "thursday": "木", + "friday": "金", + "saturday": "土", + "sunday": "日" + }, + "cancelCancellation": { + "title": "練習中止を取り消す", + "message": "{date} の「{title}」の練習中止を本当に取り消しますか?", + "confirm": "中止を取り消す" + } + }, "navigation": { "home": "ホーム", "members": "メンバー", diff --git a/frontend/src/i18n/locales/pl.json b/frontend/src/i18n/locales/pl.json index e14dc5f7..ba6b6582 100644 --- a/frontend/src/i18n/locales/pl.json +++ b/frontend/src/i18n/locales/pl.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Okres" }, + "calendar": { + "eyebrow": "Kalendarz klubu", + "title": "Kalendarz", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Dzisiaj", + "loading": "Ładowanie danych kalendarza...", + "noClub": "Najpierw wybierz klub.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Wydarzenia w tym miesiącu", + "agendaEmpty": "Brak wydarzeń w tym miesiącu.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Pon", + "tuesday": "Wt", + "wednesday": "Śr", + "thursday": "Czw", + "friday": "Pt", + "saturday": "Sob", + "sunday": "Nd" + }, + "cancelCancellation": { + "title": "Cofnij odwołanie treningu", + "message": "Na pewno cofnąć odwołanie „{title}” w dniu {date}?", + "confirm": "Cofnij odwołanie" + } + }, "navigation": { "home": "Strona główna", "members": "Członkowie", diff --git a/frontend/src/i18n/locales/th.json b/frontend/src/i18n/locales/th.json index 8410d022..47615e4b 100644 --- a/frontend/src/i18n/locales/th.json +++ b/frontend/src/i18n/locales/th.json @@ -62,6 +62,106 @@ "ok": "ตกลง", "period": "ช่วงเวลา" }, + "calendar": { + "eyebrow": "ปฏิทินสโมสร", + "title": "ปฏิทิน", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "วันนี้", + "loading": "กำลังโหลดข้อมูลปฏิทิน...", + "noClub": "โปรดเลือกสโมสรก่อน", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "กิจกรรมในเดือนนี้", + "agendaEmpty": "ไม่มีกิจกรรมในเดือนนี้", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "จ.", + "tuesday": "อ.", + "wednesday": "พ.", + "thursday": "พฤ.", + "friday": "ศ.", + "saturday": "ส.", + "sunday": "อา." + }, + "cancelCancellation": { + "title": "ยกเลิกการงดซ้อม", + "message": "ต้องการยกเลิกการงดซ้อม “{title}” วันที่ {date} หรือไม่?", + "confirm": "ยกเลิกการงดซ้อม" + } + }, "navigation": { "home": "หน้าแรก", "members": "สมาชิก", diff --git a/frontend/src/i18n/locales/tl.json b/frontend/src/i18n/locales/tl.json index 586fac10..e8fd4ac5 100644 --- a/frontend/src/i18n/locales/tl.json +++ b/frontend/src/i18n/locales/tl.json @@ -62,6 +62,106 @@ "ok": "OK", "period": "Panahon" }, + "calendar": { + "eyebrow": "Kalendaryo ng club", + "title": "Kalendaryo", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "Ngayon", + "loading": "Nilo-load ang datos ng kalendaryo...", + "noClub": "Pumili muna ng club.", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "Mga event ngayong buwan", + "agendaEmpty": "Walang event ngayong buwan.", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "Lun", + "tuesday": "Mar", + "wednesday": "Miy", + "thursday": "Huw", + "friday": "Biy", + "saturday": "Sab", + "sunday": "Lin" + }, + "cancelCancellation": { + "title": "Bawiin ang pagkansela ng training", + "message": "Bawiin talaga ang pagkansela ng training “{title}” sa {date}?", + "confirm": "Bawiin ang pagkansela" + } + }, "navigation": { "home": "Home", "members": "Mga miyembro", diff --git a/frontend/src/i18n/locales/zh.json b/frontend/src/i18n/locales/zh.json index caf549d1..d08ed114 100644 --- a/frontend/src/i18n/locales/zh.json +++ b/frontend/src/i18n/locales/zh.json @@ -62,6 +62,106 @@ "ok": "确定", "period": "期间" }, + "calendar": { + "eyebrow": "俱乐部日历", + "title": "日历", + "description": "Training days, club tournaments and league matches in a monthly view.", + "today": "今天", + "loading": "正在加载日历数据...", + "noClub": "请先选择俱乐部。", + "loadError": "Calendar data could not be loaded.", + "sourceWarning": "{source} could not be loaded", + "agendaTitle": "本月活动", + "agendaEmpty": "本月没有活动。", + "recurringTrainingTime": "Regular training time", + "participants": "{count} participants", + "starts": "{count} starts", + "options": { + "title": "Options", + "subtitle": "Cancellations & own events" + }, + "legend": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Participation", + "match": "League match", + "holiday": "Holiday", + "schoolHoliday": "School holidays", + "trainingCancellation": "Cancelled", + "customEvent": "Event" + }, + "cancellation": { + "title": "Training cancelled", + "description": "Hides regular training times.", + "date": "Date", + "untilOptional": "Until optional", + "trainingGroups": "Training groups", + "reasonPlaceholder": "Reason (optional)", + "saving": "Saving...", + "submit": "Add", + "fallbackTitle": "Training cancelled", + "subtitle": "Training cancellation" + }, + "customEvent": { + "title": "Own events", + "description": "District meetings, sessions, internal meetings, ...", + "titlePlaceholder": "Title", + "categoryPlaceholder": "Category (optional)", + "saving": "Saving...", + "submit": "Create", + "subtitleFallback": "Own event" + }, + "quickCancellation": { + "title": "Training cancellation", + "message": "Mark “{title}” as training cancellation?", + "useWholeRange": "Apply to the full period ({start} to {end})", + "trainingGroups": "Affected training groups", + "confirm": "Add cancellation", + "noGroups": "No training groups with training times are available." + }, + "sources": { + "trainingDays": "Training days", + "trainingTimes": "Training times", + "trainingCancellations": "Training cancellations", + "customEvents": "Own events", + "tournaments": "Tournaments", + "officialTournaments": "Tournament participations", + "matches": "League matches", + "holidays": "Holidays/school holidays" + }, + "eventTitles": { + "training": "Training", + "tournament": "Tournament", + "officialTournament": "Tournament participation", + "match": "League match" + }, + "tournament": { + "open": "Open tournament", + "club": "Club tournament" + }, + "match": { + "home": "Home", + "guest": "Away" + }, + "holidayTypes": { + "holiday": "Holiday", + "schoolHoliday": "School holidays" + }, + "weekdays": { + "monday": "周一", + "tuesday": "周二", + "wednesday": "周三", + "thursday": "周四", + "friday": "周五", + "saturday": "周六", + "sunday": "周日" + }, + "cancelCancellation": { + "title": "取消训练停课", + "message": "确定要取消 {date} 的“{title}”训练停课吗?", + "confirm": "取消停课" + } + }, "navigation": { "home": "首页", "members": "成员", diff --git a/frontend/src/views/CalendarView.vue b/frontend/src/views/CalendarView.vue index 7f861609..38f0eba2 100644 --- a/frontend/src/views/CalendarView.vue +++ b/frontend/src/views/CalendarView.vue @@ -2,13 +2,13 @@
- Vereinskalender -

Kalender

-

Trainingstage, Vereinsturniere und Punktspiele in einer Monatsansicht.

+ {{ $t('calendar.eyebrow') }} +

{{ $t('calendar.title') }}

+

{{ $t('calendar.description') }}

- +
@@ -31,27 +31,39 @@
- Optionen - Ausfälle & eigene Termine + {{ $t('calendar.options.title') }} + {{ $t('calendar.options.subtitle') }}
-

Training fällt aus

-

Blendet regelmäßige Trainingszeiten aus.

+

{{ $t('calendar.cancellation.title') }}

+

{{ $t('calendar.cancellation.description') }}

- + +
@@ -60,28 +72,28 @@ :key="`cancel-${cancellation.cancellationId}`" type="button" class="training-cancellation-item" - @click="deleteTrainingCancellation(cancellation)" - title="Löschen" + @click="openTrainingCancellationDeleteDialog(cancellation)" + :title="$t('common.delete')" > {{ formatShortDate(cancellation.date) }} {{ cancellation.title }} - Löschen + {{ $t('common.delete') }}
-

Eigene Termine

-

Kreistage, Sitzungen, interne Meetings, ...

+

{{ $t('calendar.customEvent.title') }}

+

{{ $t('calendar.customEvent.description') }}

- + - +
@@ -91,11 +103,11 @@ type="button" class="custom-event-item" @click="deleteCustomEvent(event)" - title="Löschen" + :title="$t('common.delete')" > {{ formatEventDate(event) }} {{ event.title }} - Löschen + {{ $t('common.delete') }}
@@ -105,12 +117,12 @@
{{ sourceWarnings.join(' · ') }}
-
Kalenderdaten werden geladen...
+
{{ $t('calendar.loading') }}
{{ error }}
-
Bitte zuerst einen Verein auswählen.
+
{{ $t('calendar.noClub') }}
-
+
{{ day }}
-

Termine im Monat

-

Keine Termine in diesem Monat.

+

{{ $t('calendar.agendaTitle') }}

+

{{ $t('calendar.agendaEmpty') }}

- + +
+

+ {{ $t('calendar.quickCancellation.message', { title: quickCancellationDialog.eventTitle }) }} +

+ + +

+ {{ $t('calendar.quickCancellation.noGroups') }} +

+
+ +
+ + +
+

+ {{ $t('calendar.cancelCancellation.message', { + title: cancellationDeleteDialog.title, + date: cancellationDeleteDialog.dateLabel + }) }} +

+

+ {{ cancellationDeleteDialog.subtitle }} +

+
+ +