fix(i18n): add missing marketplace.accessDenied and translate calendar form

- Add marketplace.accessDenied to de.json and en.json
- Add 12 calendar form field/action keys to widgets.calendar in both locales
- Replace all hardcoded English strings in calendar-source-form.tsx with t() calls
- Remove locale-detection hack on Cancel button (was comparing t() result to English string)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 12:05:52 +02:00
parent eebceb298d
commit e5b76b735a
3 changed files with 66 additions and 18 deletions
@@ -83,16 +83,16 @@ export function CalendarSourceForm({
try {
const parsed = new URL(value);
if (parsed.protocol !== 'https:') {
setUrlError('URL must use HTTPS protocol');
setUrlError(t('calendar.formUrlErrorHttps'));
return false;
}
setUrlError('');
return true;
} catch {
setUrlError('Invalid URL format');
setUrlError(t('calendar.formUrlErrorInvalid'));
return false;
}
}, []);
}, [t]);
// Form is valid when name, type, and url are filled and url is https
const isFormValid =
@@ -136,7 +136,7 @@ export function CalendarSourceForm({
{/* Name */}
<div>
<label htmlFor="source-name" className="mb-1 block text-sm text-foreground">
Name *
{t('calendar.formFieldName')} *
</label>
<input
id="source-name"
@@ -151,7 +151,7 @@ export function CalendarSourceForm({
{/* Type */}
<div>
<label htmlFor="source-type" className="mb-1 block text-sm text-foreground">
Type *
{t('calendar.formFieldType')} *
</label>
<select
id="source-type"
@@ -176,7 +176,7 @@ export function CalendarSourceForm({
htmlFor="exchange-mode"
className="mb-1 block text-sm text-foreground"
>
Exchange Mode
{t('calendar.formFieldExchangeMode')}
</label>
<select
id="exchange-mode"
@@ -196,7 +196,7 @@ export function CalendarSourceForm({
{/* URL */}
<div>
<label htmlFor="source-url" className="mb-1 block text-sm text-foreground">
URL *
{t('calendar.formFieldUrl')} *
</label>
<input
id="source-url"
@@ -228,7 +228,7 @@ export function CalendarSourceForm({
htmlFor="source-username"
className="mb-1 block text-sm text-foreground"
>
Username
{t('calendar.formFieldUsername')}
</label>
<input
id="source-username"
@@ -247,7 +247,7 @@ export function CalendarSourceForm({
htmlFor="source-password"
className="mb-1 block text-sm text-foreground"
>
Password
{t('calendar.formFieldPassword')}
</label>
<input
id="source-password"
@@ -261,7 +261,7 @@ export function CalendarSourceForm({
{/* Color */}
<div>
<label className="mb-1 block text-sm text-foreground">Color</label>
<label className="mb-1 block text-sm text-foreground">{t('calendar.formFieldColor')}</label>
<div className="flex gap-2">
{SOURCE_COLOR_PALETTE.map((c) => (
<button
@@ -288,14 +288,14 @@ export function CalendarSourceForm({
disabled={!isFormValid || isSaving}
className="rounded bg-primary px-4 py-2 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed"
>
{isSaving ? 'Saving...' : 'Save'}
{isSaving ? t('calendar.formSaving') : t('calendar.formSave')}
</button>
<button
type="button"
onClick={onCancel}
className="rounded border border-border px-4 py-2 text-sm text-foreground transition-colors hover:bg-muted"
>
{t('calendar.addSource') === 'Add source' ? 'Cancel' : 'Abbrechen'}
{t('calendar.formCancel')}
</button>
</div>
</form>
+27 -3
View File
@@ -124,6 +124,15 @@
"uploadCta": "Bild hochladen",
"uploadSuccess": "Profilbild wurde erfolgreich aktualisiert.",
"uploadError": "Hochladen fehlgeschlagen. Bitte pruefen Sie das Dateiformat und die Dateigröße.",
"deleteAvatarCta": "Bild löschen",
"deleteAvatarSuccess": "Profilbild wurde gelöscht.",
"deleteAvatarError": "Löschen fehlgeschlagen.",
"accentColorLabel": "Akzentfarbe",
"accentColorHelp": "Wird für Buttons, Highlights und aktive Elemente verwendet. Standard: #ffed00.",
"accentColorSave": "Farbe speichern",
"accentColorReset": "Zurücksetzen",
"accentColorSuccess": "Akzentfarbe wurde gespeichert.",
"accentColorError": "Speichern fehlgeschlagen.",
"ldapManagedNotice": "Ihr Passwort wird ueber das Verzeichnis (LDAP) verwaltet. Eine Aenderung ist hier nicht moeglich.",
"passwordSectionTitle": "Passwort aendern"
},
@@ -185,13 +194,27 @@
"connectionSuccess": "Verbindung erfolgreich",
"connectionError": "Verbindung fehlgeschlagen. Bitte ueberpruefen Sie die URL und Zugangsdaten.",
"addSource": "Quelle hinzufuegen",
"sourceEmpty": "Keine Kalenderquellen eingerichtet. Fuegen Sie eine Quelle hinzu, um Termine anzuzeigen."
"sourceEmpty": "Keine Kalenderquellen eingerichtet. Fuegen Sie eine Quelle hinzu, um Termine anzuzeigen.",
"formFieldName": "Name",
"formFieldType": "Typ",
"formFieldUrl": "URL",
"formFieldUsername": "Benutzername",
"formFieldPassword": "Passwort",
"formFieldColor": "Farbe",
"formFieldExchangeMode": "Exchange-Modus",
"formSave": "Speichern",
"formSaving": "Wird gespeichert...",
"formCancel": "Abbrechen",
"formUrlErrorHttps": "URL muss HTTPS verwenden",
"formUrlErrorInvalid": "Ungültiges URL-Format"
},
"note": {
"name": "Notizen",
"description": "Freitext-Notizen mit Markdown",
"defaultTitle": "Notiz",
"autosaveError": "Speichern fehlgeschlagen"
"autosaveError": "Speichern fehlgeschlagen",
"editMode": "Bearbeiten",
"viewMode": "Vorschau"
},
"calculator": {
"name": "Taschenrechner",
@@ -434,6 +457,7 @@
"backToMarketplace": "Zurueck zum Marktplatz",
"detailVersion": "Version {version}",
"detailStatusActive": "Aktiviert fuer diesen Mandanten",
"detailStatusInactive": "Nicht aktiviert"
"detailStatusInactive": "Nicht aktiviert",
"accessDenied": "Zugriff verweigert"
}
}
+27 -3
View File
@@ -124,6 +124,15 @@
"uploadCta": "Upload picture",
"uploadSuccess": "Profile picture updated successfully.",
"uploadError": "Upload failed. Please check the file format and size.",
"deleteAvatarCta": "Delete picture",
"deleteAvatarSuccess": "Profile picture deleted.",
"deleteAvatarError": "Delete failed.",
"accentColorLabel": "Accent Color",
"accentColorHelp": "Used for buttons, highlights and active elements. Default: #ffed00.",
"accentColorSave": "Save color",
"accentColorReset": "Reset",
"accentColorSuccess": "Accent color saved.",
"accentColorError": "Save failed.",
"ldapManagedNotice": "Your password is managed via the directory (LDAP) and cannot be changed here.",
"passwordSectionTitle": "Change Password"
},
@@ -185,13 +194,27 @@
"connectionSuccess": "Connection successful",
"connectionError": "Connection failed. Please check the URL and credentials.",
"addSource": "Add source",
"sourceEmpty": "No calendar sources configured. Add a source to display events."
"sourceEmpty": "No calendar sources configured. Add a source to display events.",
"formFieldName": "Name",
"formFieldType": "Type",
"formFieldUrl": "URL",
"formFieldUsername": "Username",
"formFieldPassword": "Password",
"formFieldColor": "Color",
"formFieldExchangeMode": "Exchange Mode",
"formSave": "Save",
"formSaving": "Saving...",
"formCancel": "Cancel",
"formUrlErrorHttps": "URL must use HTTPS protocol",
"formUrlErrorInvalid": "Invalid URL format"
},
"note": {
"name": "Notes",
"description": "Free-text notes with Markdown",
"defaultTitle": "Note",
"autosaveError": "Save failed"
"autosaveError": "Save failed",
"editMode": "Edit",
"viewMode": "Preview"
},
"calculator": {
"name": "Calculator",
@@ -434,6 +457,7 @@
"backToMarketplace": "Back to Marketplace",
"detailVersion": "Version {version}",
"detailStatusActive": "Activated for this tenant",
"detailStatusInactive": "Not activated"
"detailStatusInactive": "Not activated",
"accessDenied": "Access denied"
}
}