Skip to content
This repository was archived by the owner on May 5, 2026. It is now read-only.

Commit 72921a9

Browse files
committed
c/fix(pwa): notification text appears in correct language
Adding the notification too early ment the i18n translation was not yet loaded properly. The notification object is now a subscribable store to make sure the translations are working at render time Signed-off-by: Kai Henseler <kai.henseler@strato.de>
1 parent 6787843 commit 72921a9

3 files changed

Lines changed: 58 additions & 47 deletions

File tree

src/lib/IONOS/components/notifications/NotificationBanner.svelte

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,38 @@
77
import EmojiSad from '$lib/IONOS/components/icons/EmojiSad.svelte';
88
import Touch from '$lib/IONOS/components/icons/Touch.svelte';
99
import Link from '$lib/IONOS/components/common/Link.svelte';
10-
import { NotificationType, type Notification } from '$lib/IONOS/stores/notifications';
10+
import { NotificationType, type SubscribableNotification } from '$lib/IONOS/stores/notifications';
1111
import { createEventDispatcher, getContext } from 'svelte';
1212
1313
const dispatch = createEventDispatcher();
1414
const i18n = getContext<Readable<I18Next>>('i18n');
1515
16-
export let notification: Notification;
16+
export let notification: SubscribableNotification;
1717
</script>
1818

1919

20-
<div transition:fly={{ y: -200, duration: 50 }} class="ease-in-out w-full p-4 sm:p-5 flex items-center justify-start text-sm gap-2 {notification.type}">
20+
<div transition:fly={{ y: -200, duration: 50 }} class="ease-in-out w-full p-4 sm:p-5 flex items-center justify-start text-sm gap-2 {$notification.type}">
2121
<div id="notification-icon" class="self-start pt-0.5 sm:pt-0">
22-
{#if notification.type === NotificationType.FEEDBACK}
22+
{#if $notification.type === NotificationType.FEEDBACK}
2323
<Heart />
24-
{:else if notification.type === NotificationType.ERROR}
24+
{:else if $notification.type === NotificationType.ERROR}
2525
<EmojiSad className="text-red-500"/>
26-
{:else if notification.type === NotificationType.INFO}
26+
{:else if $notification.type === NotificationType.INFO}
2727
<Touch />
2828
{/if}
2929
</div>
3030
<div class="flex flex-col md:flex-row gap-2.5 items-start">
3131
<p>
32-
<span class="font-semibold">{notification.title}</span>
33-
{notification.message}
32+
<span class="font-semibold">{$notification.title}</span>
33+
{$notification.message}
3434
</p>
35-
{#each notification.actions as action}
35+
{#each $notification.actions as action}
3636
<Link href={action.href ?? ''} className="text-blue-600 underline" on:click={action.handler}>
3737
{action.label}
3838
</Link>
3939
{/each}
4040
</div>
41-
{#if notification.dismissible}
41+
{#if $notification.dismissible}
4242
<button class="ml-auto hover:text-red-500 active:text-red-400" on:click={() => dispatch('dismiss', { notification })}>
4343
<XMark />
4444
</button>

src/lib/IONOS/components/notifications/NotificationManager.svelte

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
<script lang="ts">
2-
import type { Readable } from 'svelte/store';
2+
import { type Readable, get } from 'svelte/store';
33
import type { I18Next } from '$lib/IONOS/i18next.d.ts';
44
import type { Chat } from '$lib/apis/chats/types.ts';
55
import NotificationBanner from "$lib/IONOS/components/notifications/NotificationBanner.svelte";
66
import PWAInstallDialog from "$lib/IONOS/components/notifications/PWAInstallDialog.svelte";
77
import { chats, user } from '$lib/stores';
88
import { updateSettings } from '$lib/IONOS/services/settings';
99
import { buildSurveyUrl } from '$lib/IONOS/services/survey';
10-
import { notifications, addNotification, removeNotification, type Notification, NotificationType } from "$lib/IONOS/stores/notifications";
10+
import { notifications, addNotification, removeNotification, type Notification, type SubscribableNotification, NotificationType } from "$lib/IONOS/stores/notifications";
1111
import { getContext, onDestroy, onMount } from 'svelte';
1212
import { getUserSettings } from '$lib/apis/users';
1313
import {
@@ -42,28 +42,34 @@
4242
return;
4343
}
4444
45-
const surveyNotification: Notification = {
46-
id: "survey",
47-
type: NotificationType.FEEDBACK,
48-
title: $i18n.t('Love our product?', { ns: 'ionos' }),
49-
message: $i18n.t('Help us improve', { ns: 'ionos' }),
50-
actions: [{
51-
label: $i18n.t('Take Our Quick Survey', { ns: 'ionos' }),
52-
handler: () => {
53-
window.open(surveyUrl, '_blank', "noopener=yes,noreferrer=yes");
54-
updateSettings({
55-
ionosProvidedFeedback: true
45+
const surveyNotification = {
46+
subscribe: (fn: (notification: Notification) => void) => {
47+
return i18n.subscribe(() => {
48+
fn({
49+
id: "survey",
50+
type: NotificationType.FEEDBACK,
51+
title: $i18n.t('Love our product?', { ns: 'ionos' }),
52+
message: $i18n.t('Help us improve', { ns: 'ionos' }),
53+
actions: [{
54+
label: $i18n.t('Take Our Quick Survey', { ns: 'ionos' }),
55+
handler: () => {
56+
window.open(surveyUrl, '_blank', "noopener=yes,noreferrer=yes");
57+
updateSettings({
58+
ionosProvidedFeedback: true
59+
});
60+
}
61+
}],
5662
});
57-
}
58-
}],
59-
}
63+
});
64+
}
65+
};
6066
addNotification(surveyNotification);
6167
};
6268
6369
const dismissHandler = (event: CustomEvent) => {
6470
const notification = event.detail.notification;
6571
66-
if (notification.type === NotificationType.PWA_INSTALL) {
72+
if (get(notification).type === NotificationType.PWA_INSTALL) {
6773
dismissPWAPrompt();
6874
}
6975
@@ -92,18 +98,24 @@
9298
}
9399
94100
const addPWANotification = () => {
95-
const pwaNotification: Notification = {
96-
id: "pwa",
97-
type: NotificationType.PWA_INSTALL,
98-
title: $i18n.t('Install IONOS GPT', { ns: 'ionos' }),
99-
message: $i18n.t('For quick and easy access, you can now install IONOS GPT like an app!', { ns: 'ionos' }),
100-
actions: [{
101-
label: $i18n.t('Install', { ns: 'ionos' }),
102-
handler: () => {
103-
handlePWAInstall();
104-
}
105-
}],
106-
dismissible: true,
101+
const pwaNotification = {
102+
subscribe: (fn: (notification: Notification) => void) => {
103+
return i18n.subscribe(() => {
104+
fn({
105+
id: "pwa",
106+
type: NotificationType.PWA_INSTALL,
107+
title: $i18n.t('Install IONOS GPT', { ns: 'ionos' }),
108+
message: $i18n.t('For quick and easy access, you can now install IONOS GPT like an app!', { ns: 'ionos' }),
109+
actions: [{
110+
label: $i18n.t('Install', { ns: 'ionos' }),
111+
handler: () => {
112+
handlePWAInstall();
113+
}
114+
}],
115+
dismissible: true,
116+
});
117+
});
118+
}
107119
};
108120
addNotification(pwaNotification);
109121
};

src/lib/IONOS/stores/notifications.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type Writable, writable } from 'svelte/store';
1+
import { type Writable, writable, type Readable } from 'svelte/store';
22

33
export enum NotificationType {
44
INFO = 'bg-blue-100 text-blue-800',
@@ -38,14 +38,13 @@ export type Notification = {
3838
dismissible?: boolean;
3939
};
4040

41-
export const notifications: Writable<Notification[]> = writable([]);
41+
export type SubscribableNotification = Readable<Notification>;
4242

43-
export const addNotification = (notification: Notification): void => {
44-
notifications.update((currentNotifications: Notification[]) => {
45-
if (currentNotifications.some(n => n.title === notification.title)) {
46-
return currentNotifications;
47-
}
48-
return [...currentNotifications, notification]
43+
export const notifications: Writable<SubscribableNotification[]> = writable([]);
44+
45+
export const addNotification = (notification: SubscribableNotification): void => {
46+
notifications.update((currentNotifications: SubscribableNotification[]) => {
47+
return [...currentNotifications, notification];
4948
});
5049
};
5150

0 commit comments

Comments
 (0)