diff --git a/apps/mana/apps/web/src/lib/i18n/locales/gifts/de.json b/apps/mana/apps/web/src/lib/i18n/locales/gifts/de.json index 039357613..f41567aaf 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/gifts/de.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/gifts/de.json @@ -65,5 +65,40 @@ "status_refunded": "Erstattet", "type_simple_label": "Einfach", "type_personalized_label": "Persönlich" + }, + "redeem": { + "page_back_title": "Gutschein", + "page_title": "Geschenk einlösen", + "page_description": "Löse deinen Geschenk-Code ein", + "err_not_found": "Geschenk-Code nicht gefunden", + "err_redeem_failed": "Einlösen fehlgeschlagen", + "toast_received": "{credits} Credits erhalten!", + "success_heading": "Geschenk eingelöst!", + "success_credits_label": "Credits erhalten", + "success_balance_html": "Dein neuer Kontostand: {balance} Credits", + "success_link_credits": "Zu meinen Credits", + "success_link_overview": "Geschenke ansehen", + "action_other_code": "Anderen Code eingeben", + "label_from": "Von {name}", + "label_you_get": "Du erhältst", + "label_credits": "Credits", + "label_type": "Art", + "label_status": "Status", + "label_valid_until": "Gültig bis", + "label_message_prefix": "Nachricht:", + "section_redeem": "Einlösen", + "warn_depleted": "Dieses Geschenk wurde bereits eingelöst", + "warn_expired": "Dieses Geschenk ist abgelaufen", + "warn_other": "Dieses Geschenk kann nicht eingelöst werden", + "info_personalized": "Dieses Geschenk ist für eine bestimmte Person. Nur der vorgesehene Empfänger kann es einlösen.", + "action_redeeming": "Wird eingelöst...", + "action_redeem": "🎁 Geschenk einlösen", + "type_simple": "Geschenk", + "type_personalized": "Persönliches Geschenk", + "status_active": "Aktiv", + "status_depleted": "Aufgebraucht", + "status_expired": "Abgelaufen", + "status_cancelled": "Storniert", + "status_refunded": "Erstattet" } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/gifts/en.json b/apps/mana/apps/web/src/lib/i18n/locales/gifts/en.json index c75becee7..8b3d0bf66 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/gifts/en.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/gifts/en.json @@ -65,5 +65,40 @@ "status_refunded": "Refunded", "type_simple_label": "Simple", "type_personalized_label": "Personalized" + }, + "redeem": { + "page_back_title": "Voucher", + "page_title": "Redeem gift", + "page_description": "Redeem your gift code", + "err_not_found": "Gift code not found", + "err_redeem_failed": "Redeem failed", + "toast_received": "{credits} credits received!", + "success_heading": "Gift redeemed!", + "success_credits_label": "credits received", + "success_balance_html": "Your new balance: {balance} credits", + "success_link_credits": "Go to my credits", + "success_link_overview": "View gifts", + "action_other_code": "Enter another code", + "label_from": "From {name}", + "label_you_get": "You'll receive", + "label_credits": "Credits", + "label_type": "Type", + "label_status": "Status", + "label_valid_until": "Valid until", + "label_message_prefix": "Message:", + "section_redeem": "Redeem", + "warn_depleted": "This gift has already been redeemed", + "warn_expired": "This gift has expired", + "warn_other": "This gift can't be redeemed", + "info_personalized": "This gift is for a specific person. Only the intended recipient can redeem it.", + "action_redeeming": "Redeeming…", + "action_redeem": "🎁 Redeem gift", + "type_simple": "Gift", + "type_personalized": "Personalized gift", + "status_active": "Active", + "status_depleted": "Depleted", + "status_expired": "Expired", + "status_cancelled": "Cancelled", + "status_refunded": "Refunded" } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/gifts/es.json b/apps/mana/apps/web/src/lib/i18n/locales/gifts/es.json index e8b872326..62b4158a5 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/gifts/es.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/gifts/es.json @@ -65,5 +65,40 @@ "status_refunded": "Reembolsado", "type_simple_label": "Simple", "type_personalized_label": "Personalizado" + }, + "redeem": { + "page_back_title": "Vale", + "page_title": "Canjear regalo", + "page_description": "Canjea tu código de regalo", + "err_not_found": "Código de regalo no encontrado", + "err_redeem_failed": "Canje fallido", + "toast_received": "¡{credits} credits recibidos!", + "success_heading": "¡Regalo canjeado!", + "success_credits_label": "credits recibidos", + "success_balance_html": "Nuevo saldo: {balance} credits", + "success_link_credits": "A mis credits", + "success_link_overview": "Ver regalos", + "action_other_code": "Introducir otro código", + "label_from": "De {name}", + "label_you_get": "Recibes", + "label_credits": "Credits", + "label_type": "Tipo", + "label_status": "Estado", + "label_valid_until": "Válido hasta", + "label_message_prefix": "Mensaje:", + "section_redeem": "Canjear", + "warn_depleted": "Este regalo ya ha sido canjeado", + "warn_expired": "Este regalo ha expirado", + "warn_other": "Este regalo no puede canjearse", + "info_personalized": "Este regalo es para una persona concreta. Solo el destinatario puede canjearlo.", + "action_redeeming": "Canjeando…", + "action_redeem": "🎁 Canjear regalo", + "type_simple": "Regalo", + "type_personalized": "Regalo personalizado", + "status_active": "Activo", + "status_depleted": "Agotado", + "status_expired": "Expirado", + "status_cancelled": "Cancelado", + "status_refunded": "Reembolsado" } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/gifts/fr.json b/apps/mana/apps/web/src/lib/i18n/locales/gifts/fr.json index 41c60179b..18831e768 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/gifts/fr.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/gifts/fr.json @@ -65,5 +65,40 @@ "status_refunded": "Remboursé", "type_simple_label": "Simple", "type_personalized_label": "Personnalisé" + }, + "redeem": { + "page_back_title": "Bon", + "page_title": "Utiliser le cadeau", + "page_description": "Utilise ton code cadeau", + "err_not_found": "Code cadeau introuvable", + "err_redeem_failed": "Échec de l'utilisation", + "toast_received": "{credits} crédits reçus !", + "success_heading": "Cadeau utilisé !", + "success_credits_label": "crédits reçus", + "success_balance_html": "Nouveau solde : {balance} crédits", + "success_link_credits": "Voir mes crédits", + "success_link_overview": "Voir les cadeaux", + "action_other_code": "Saisir un autre code", + "label_from": "De {name}", + "label_you_get": "Tu reçois", + "label_credits": "Crédits", + "label_type": "Type", + "label_status": "Statut", + "label_valid_until": "Valide jusqu'au", + "label_message_prefix": "Message :", + "section_redeem": "Utiliser", + "warn_depleted": "Ce cadeau a déjà été utilisé", + "warn_expired": "Ce cadeau a expiré", + "warn_other": "Ce cadeau ne peut pas être utilisé", + "info_personalized": "Ce cadeau est destiné à une personne précise. Seul le destinataire prévu peut l'utiliser.", + "action_redeeming": "Utilisation…", + "action_redeem": "🎁 Utiliser le cadeau", + "type_simple": "Cadeau", + "type_personalized": "Cadeau personnalisé", + "status_active": "Actif", + "status_depleted": "Épuisé", + "status_expired": "Expiré", + "status_cancelled": "Annulé", + "status_refunded": "Remboursé" } } diff --git a/apps/mana/apps/web/src/lib/i18n/locales/gifts/it.json b/apps/mana/apps/web/src/lib/i18n/locales/gifts/it.json index b56686e0e..b3f00fc42 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/gifts/it.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/gifts/it.json @@ -65,5 +65,40 @@ "status_refunded": "Rimborsato", "type_simple_label": "Semplice", "type_personalized_label": "Personalizzato" + }, + "redeem": { + "page_back_title": "Buono", + "page_title": "Riscatta regalo", + "page_description": "Riscatta il tuo codice regalo", + "err_not_found": "Codice regalo non trovato", + "err_redeem_failed": "Riscatto non riuscito", + "toast_received": "{credits} credits ricevuti!", + "success_heading": "Regalo riscattato!", + "success_credits_label": "credits ricevuti", + "success_balance_html": "Nuovo saldo: {balance} credits", + "success_link_credits": "Ai miei credits", + "success_link_overview": "Vedi regali", + "action_other_code": "Inserisci un altro codice", + "label_from": "Da {name}", + "label_you_get": "Ricevi", + "label_credits": "Credits", + "label_type": "Tipo", + "label_status": "Stato", + "label_valid_until": "Valido fino a", + "label_message_prefix": "Messaggio:", + "section_redeem": "Riscatta", + "warn_depleted": "Questo regalo è già stato riscattato", + "warn_expired": "Questo regalo è scaduto", + "warn_other": "Questo regalo non può essere riscattato", + "info_personalized": "Questo regalo è per una persona specifica. Solo il destinatario può riscattarlo.", + "action_redeeming": "Riscatto in corso…", + "action_redeem": "🎁 Riscatta regalo", + "type_simple": "Regalo", + "type_personalized": "Regalo personalizzato", + "status_active": "Attivo", + "status_depleted": "Esaurito", + "status_expired": "Scaduto", + "status_cancelled": "Annullato", + "status_refunded": "Rimborsato" } } diff --git a/apps/mana/apps/web/src/routes/(app)/gifts/redeem/[code]/+page.svelte b/apps/mana/apps/web/src/routes/(app)/gifts/redeem/[code]/+page.svelte index 33816563e..9be52851e 100644 --- a/apps/mana/apps/web/src/routes/(app)/gifts/redeem/[code]/+page.svelte +++ b/apps/mana/apps/web/src/routes/(app)/gifts/redeem/[code]/+page.svelte @@ -6,6 +6,8 @@ import { toast } from '$lib/stores/toast.svelte'; import { giftsService, type GiftCodeInfo } from '$lib/api/gifts'; import { RoutePage } from '$lib/components/shell'; + import { _, locale } from 'svelte-i18n'; + import { get } from 'svelte/store'; let code = $derived($page.params.code ?? ''); let giftInfo = $state(null); @@ -29,7 +31,7 @@ try { giftInfo = await giftsService.getGiftInfo(code); } catch (e) { - error = e instanceof Error ? e.message : 'Geschenk-Code nicht gefunden'; + error = e instanceof Error ? e.message : $_('gifts.redeem.err_not_found'); console.error('Failed to load gift info:', e); } finally { loading = false; @@ -49,13 +51,13 @@ success = true; receivedCredits = result.credits || 0; newBalance = result.newBalance || 0; - toast.success(`${receivedCredits} Credits erhalten!`); + toast.success($_('gifts.redeem.toast_received', { values: { credits: receivedCredits } })); } else { - error = result.error || 'Einlösen fehlgeschlagen'; + error = result.error || $_('gifts.redeem.err_redeem_failed'); toast.error(error); } } catch (e) { - error = e instanceof Error ? e.message : 'Einlösen fehlgeschlagen'; + error = e instanceof Error ? e.message : $_('gifts.redeem.err_redeem_failed'); toast.error(error); console.error('Failed to redeem gift:', e); } finally { @@ -64,7 +66,7 @@ } function formatDate(dateStr: string): string { - return new Date(dateStr).toLocaleDateString('de-DE', { + return new Date(dateStr).toLocaleDateString(get(locale) ?? 'de', { day: '2-digit', month: '2-digit', year: 'numeric', @@ -74,15 +76,15 @@ function getStatusLabel(status: string): string { switch (status) { case 'active': - return 'Aktiv'; + return $_('gifts.redeem.status_active'); case 'depleted': - return 'Aufgebraucht'; + return $_('gifts.redeem.status_depleted'); case 'expired': - return 'Abgelaufen'; + return $_('gifts.redeem.status_expired'); case 'cancelled': - return 'Storniert'; + return $_('gifts.redeem.status_cancelled'); case 'refunded': - return 'Erstattet'; + return $_('gifts.redeem.status_refunded'); default: return status; } @@ -91,18 +93,22 @@ function getTypeLabel(type: string): string { switch (type) { case 'simple': - return 'Geschenk'; + return $_('gifts.redeem.type_simple'); case 'personalized': - return 'Persönliches Geschenk'; + return $_('gifts.redeem.type_personalized'); default: return type; } } - +
- + {#if loading}
@@ -119,24 +125,26 @@ > 🎉
-

Geschenk eingelöst!

+

{$_('gifts.redeem.success_heading')}

+{receivedCredits}

-

Credits erhalten

+

{$_('gifts.redeem.success_credits_label')}

- Dein neuer Kontostand: {newBalance} Credits + {@html $_('gifts.redeem.success_balance_html', { + values: { balance: newBalance }, + })}

@@ -155,7 +163,7 @@ href="/gifts/redeem" class="inline-block rounded-lg bg-primary px-6 py-2 text-primary-foreground hover:bg-primary/90" > - Anderen Code eingeben + {$_('gifts.redeem.action_other_code')} @@ -171,23 +179,27 @@

{giftInfo.code}

{#if giftInfo.creatorName} -

Von {giftInfo.creatorName}

+

+ {$_('gifts.redeem.label_from', { + values: { name: giftInfo.creatorName }, + })} +

{/if}
-

Du erhältst

+

{$_('gifts.redeem.label_you_get')}

{giftInfo.totalCredits}

-

Credits

+

{$_('gifts.redeem.label_credits')}

- Art + {$_('gifts.redeem.label_type')} {getTypeLabel(giftInfo.type)}
- Status + {$_('gifts.redeem.label_status')} - Gültig bis + {$_('gifts.redeem.label_valid_until')} {formatDate(giftInfo.expiresAt)}
{/if} @@ -206,7 +218,9 @@ {#if giftInfo.message}
-

Nachricht:

+

+ {$_('gifts.redeem.label_message_prefix')} +

"{giftInfo.message}"

{/if} @@ -214,17 +228,17 @@ -

Einlösen

+

{$_('gifts.redeem.section_redeem')}

{#if giftInfo.status !== 'active'}

{#if giftInfo.status === 'depleted'} - Dieses Geschenk wurde bereits eingelöst + {$_('gifts.redeem.warn_depleted')} {:else if giftInfo.status === 'expired'} - Dieses Geschenk ist abgelaufen + {$_('gifts.redeem.warn_expired')} {:else} - Dieses Geschenk kann nicht eingelöst werden + {$_('gifts.redeem.warn_other')} {/if}

@@ -234,8 +248,7 @@
👤

- Dieses Geschenk ist für eine bestimmte Person. Nur der vorgesehene Empfänger - kann es einlösen. + {$_('gifts.redeem.info_personalized')}

@@ -268,16 +281,16 @@ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" > - Wird eingelöst... + {$_('gifts.redeem.action_redeeming')} {:else} - 🎁 Geschenk einlösen + {$_('gifts.redeem.action_redeem')} {/if} {/if} diff --git a/scripts/i18n-hardcoded-baseline.json b/scripts/i18n-hardcoded-baseline.json index 7507d2721..c7e481f82 100644 --- a/scripts/i18n-hardcoded-baseline.json +++ b/scripts/i18n-hardcoded-baseline.json @@ -230,7 +230,6 @@ "apps/mana/apps/web/src/routes/(app)/food/+page.svelte": 7, "apps/mana/apps/web/src/routes/(app)/food/add/+page.svelte": 2, "apps/mana/apps/web/src/routes/(app)/food/goals/+page.svelte": 1, - "apps/mana/apps/web/src/routes/(app)/gifts/redeem/[code]/+page.svelte": 8, "apps/mana/apps/web/src/routes/(app)/gifts/redeem/+page.svelte": 1, "apps/mana/apps/web/src/routes/(app)/guides/+page.svelte": 2, "apps/mana/apps/web/src/routes/(app)/habits/[id]/+page.svelte": 3, @@ -317,6 +316,7 @@ "apps/mana/apps/web/src/routes/community/+layout.svelte": 5, "apps/mana/apps/web/src/routes/community/+page.svelte": 1, "apps/mana/apps/web/src/routes/community/admin/+page.svelte": 6, + "apps/mana/apps/web/src/routes/community/eule/[hash]/+page.svelte": 1, "apps/mana/apps/web/src/routes/community/roadmap/+page.svelte": 1, "apps/mana/apps/web/src/routes/g/[code]/+page.svelte": 6, "apps/mana/apps/web/src/routes/rsvp/[token]/+page.svelte": 1,