Skip to content

Commit 9c85359

Browse files
feat(i18n): translate blocked scheduled message warnings
The composer now reports a composition that cannot be scheduled as validation:scheduled-message:blocked with the reason in its metadata. Translate it per reason (slash command, poll, shared location) with a generic fallback, and add the strings to all 12 locales. Refs: REACT-1387 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent baeb72f commit 9c85359

16 files changed

Lines changed: 98 additions & 13 deletions

File tree

‎src/components/ScheduledMessages/constants.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export type ScheduleMessageNoticeSeverity =
3131
(typeof ScheduleMessageNoticeSeverity)[keyof typeof ScheduleMessageNoticeSeverity];
3232

3333
export const ScheduledMessageNotificationType = {
34-
CommandRejected: 'validation:scheduled-message:command',
34+
Blocked: 'validation:scheduled-message:blocked',
3535
CreateFailed: 'api:scheduled-message:create:failed',
3636
CreateSucceeded: 'api:scheduled-message:create:success',
3737
} as const;

‎src/i18n/TranslationBuilder/notifications/translators.ts‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
ErrorFromResponse,
33
getScheduledMessageErrorReason,
4+
ScheduledMessageBlockReason,
45
ScheduledMessageErrorReason,
56
} from 'stream-chat';
67
import type { Notification } from 'stream-chat';
@@ -125,3 +126,21 @@ export const translateScheduledMessageCreateFailed: Translator<
125126

126127
return t("Couldn't schedule message. Try again");
127128
};
129+
130+
export const translateScheduledMessageBlocked: Translator<
131+
NotificationTranslatorOptions
132+
> = ({ options: { notification }, t }) => {
133+
const { reason } = notification?.metadata ?? {};
134+
135+
if (reason === ScheduledMessageBlockReason.Command) {
136+
return t("Slash commands can't be scheduled");
137+
}
138+
139+
if (reason === ScheduledMessageBlockReason.Poll) return t("Polls can't be scheduled");
140+
141+
if (reason === ScheduledMessageBlockReason.SharedLocation) {
142+
return t("Locations can't be scheduled");
143+
}
144+
145+
return t("This message can't be scheduled");
146+
};

‎src/i18n/TranslationBuilder/notifications/translatorsByNotificationType.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
translateCommandDisabled,
88
translatePollCreateFailed,
99
translatePollEndFailed,
10+
translateScheduledMessageBlocked,
1011
translateScheduledMessageCreateFailed,
1112
} from './translators';
1213
import type { Translator } from '../../index';
@@ -37,6 +38,5 @@ export const translatorsByNotificationType: Record<
3738
'validation:command:disabled': translateCommandDisabled,
3839
'validation:poll:castVote:limit': ({ t }) =>
3940
t('Reached the vote limit. Remove an existing vote first.'),
40-
[ScheduledMessageNotificationType.CommandRejected]: ({ t }) =>
41-
t("Slash commands can't be scheduled"),
41+
[ScheduledMessageNotificationType.Blocked]: translateScheduledMessageBlocked,
4242
};

‎src/i18n/__tests__/scheduledMessageNotificationTranslators.test.ts‎

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { fromPartial } from '@total-typescript/shoehorn';
22
import type { TFunction } from 'i18next';
3-
import { ErrorFromResponse } from 'stream-chat';
3+
import { ErrorFromResponse, ScheduledMessageBlockReason } from 'stream-chat';
44
import type { Notification } from 'stream-chat';
55

6-
import { translateScheduledMessageCreateFailed } from '../TranslationBuilder/notifications/translators';
6+
import {
7+
translateScheduledMessageBlocked,
8+
translateScheduledMessageCreateFailed,
9+
} from '../TranslationBuilder/notifications/translators';
710
import { translatorsByNotificationType } from '../TranslationBuilder/notifications/translatorsByNotificationType';
811

912
const t = ((key: string) => key) as TFunction;
@@ -63,18 +66,45 @@ describe('translateScheduledMessageCreateFailed', () => {
6366
});
6467
});
6568

69+
const translateBlocked = (reason?: string) =>
70+
translateScheduledMessageBlocked({
71+
key: '',
72+
options: {
73+
notification: fromPartial<Notification>({
74+
message: 'This message cannot be scheduled',
75+
metadata: reason ? { reason } : undefined,
76+
type: 'validation:scheduled-message:blocked',
77+
}),
78+
},
79+
t,
80+
value: '',
81+
});
82+
83+
describe('translateScheduledMessageBlocked', () => {
84+
it.each([
85+
[ScheduledMessageBlockReason.Command, "Slash commands can't be scheduled"],
86+
[ScheduledMessageBlockReason.Poll, "Polls can't be scheduled"],
87+
[ScheduledMessageBlockReason.SharedLocation, "Locations can't be scheduled"],
88+
])('translates the %s reason', (reason, expected) => {
89+
expect(translateBlocked(reason)).toBe(expected);
90+
});
91+
92+
it('falls back to the generic copy without a known reason', () => {
93+
expect(translateBlocked()).toBe("This message can't be scheduled");
94+
expect(translateBlocked('unknown')).toBe("This message can't be scheduled");
95+
});
96+
});
97+
6698
describe('scheduled message notification types', () => {
6799
it('registers translators for the composer notifications', () => {
68100
expect(translatorsByNotificationType['api:scheduled-message:create:failed']).toBe(
69101
translateScheduledMessageCreateFailed,
70102
);
71-
expect(
72-
translatorsByNotificationType['validation:scheduled-message:command']?.({
73-
key: '',
74-
options: {},
75-
t,
76-
value: '',
77-
}),
78-
).toBe("Slash commands can't be scheduled");
103+
expect(translatorsByNotificationType['validation:scheduled-message:blocked']).toBe(
104+
translateScheduledMessageBlocked,
105+
);
106+
expect(translatorsByNotificationType).not.toHaveProperty(
107+
'validation:scheduled-message:command',
108+
);
79109
});
80110
});

‎src/i18n/de.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@
464464
"Location": "Standort",
465465
"Location sharing ended": "Standortfreigabe beendet",
466466
"Location: {{ coordinates }}": "Standort: {{ coordinates }}",
467+
"Locations can't be scheduled": "Standorte können nicht geplant werden",
467468
"Manage channel": "Kanal verwalten",
468469
"Manage members": "Mitglieder verwalten",
469470
"Mark as unread": "Als ungelesen markieren",
@@ -546,6 +547,7 @@
546547
"Poll options": "Umfrageoptionen",
547548
"Poll results": "Umfrageergebnisse",
548549
"Poll sent": "Umfrage gesendet",
550+
"Polls can't be scheduled": "Umfragen können nicht geplant werden",
549551
"Previous": "Zurück",
550552
"Previous image": "Vorheriges Bild",
551553
"Putting on my thinking cap": "Ich setze meine Denkerkappe auf",
@@ -644,6 +646,7 @@
644646
"Thinking...": "Denken...",
645647
"this content could not be displayed": "Dieser Inhalt konnte nicht angezeigt werden",
646648
"This field cannot be empty or contain only spaces": "Dieses Feld darf nicht leer sein oder nur Leerzeichen enthalten",
649+
"This message can't be scheduled": "Diese Nachricht kann nicht geplant werden",
647650
"This message did not meet our content guidelines": "Diese Nachricht entsprach nicht unseren Inhaltsrichtlinien",
648651
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
649652
"This user will be able to message you again.": "Dieser Benutzer kann dir wieder Nachrichten senden.",

‎src/i18n/en.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@
464464
"Location": "Location",
465465
"Location sharing ended": "Location sharing ended",
466466
"Location: {{ coordinates }}": "Location: {{ coordinates }}",
467+
"Locations can't be scheduled": "Locations can't be scheduled",
467468
"Manage channel": "Manage channel",
468469
"Manage members": "Manage members",
469470
"Mark as unread": "Mark as unread",
@@ -546,6 +547,7 @@
546547
"Poll options": "Poll Options",
547548
"Poll results": "Poll Results",
548549
"Poll sent": "Poll sent",
550+
"Polls can't be scheduled": "Polls can't be scheduled",
549551
"Previous": "Previous",
550552
"Previous image": "Previous image",
551553
"Putting on my thinking cap": "Putting on my thinking cap",
@@ -644,6 +646,7 @@
644646
"Thinking...": "Thinking...",
645647
"this content could not be displayed": "this content could not be displayed",
646648
"This field cannot be empty or contain only spaces": "This field cannot be empty or contain only spaces",
649+
"This message can't be scheduled": "This message can't be scheduled",
647650
"This message did not meet our content guidelines": "This message did not meet our content guidelines",
648651
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
649652
"This user will be able to message you again.": "This user will be able to message you again.",

‎src/i18n/es.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@
484484
"Location": "Ubicación",
485485
"Location sharing ended": "Compartir ubicación terminado",
486486
"Location: {{ coordinates }}": "Ubicación: {{ coordinates }}",
487+
"Locations can't be scheduled": "Las ubicaciones no se pueden programar",
487488
"Manage channel": "Gestionar canal",
488489
"Manage members": "Gestionar miembros",
489490
"Mark as unread": "Marcar como no leído",
@@ -566,6 +567,7 @@
566567
"Poll options": "Opciones de la encuesta",
567568
"Poll results": "Resultados de la encuesta",
568569
"Poll sent": "Encuesta enviada",
570+
"Polls can't be scheduled": "Las encuestas no se pueden programar",
569571
"Previous": "Anterior",
570572
"Previous image": "Imagen anterior",
571573
"Putting on my thinking cap": "Poniéndome el gorro de pensar",
@@ -669,6 +671,7 @@
669671
"Thinking...": "Pensando...",
670672
"this content could not be displayed": "Este contenido no se pudo mostrar",
671673
"This field cannot be empty or contain only spaces": "Este campo no puede estar vacío o contener solo espacios",
674+
"This message can't be scheduled": "Este mensaje no se puede programar",
672675
"This message did not meet our content guidelines": "Este mensaje no cumple con nuestras directrices de contenido",
673676
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
674677
"This user will be able to message you again.": "Este usuario podrá enviarte mensajes de nuevo.",

‎src/i18n/fr.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@
484484
"Location": "Emplacement",
485485
"Location sharing ended": "Partage d'emplacement terminé",
486486
"Location: {{ coordinates }}": "Emplacement : {{ coordinates }}",
487+
"Locations can't be scheduled": "Les positions ne peuvent pas être programmées",
487488
"Manage channel": "Gérer le canal",
488489
"Manage members": "Gérer les membres",
489490
"Mark as unread": "Marquer comme non lu",
@@ -566,6 +567,7 @@
566567
"Poll options": "Options du sondage",
567568
"Poll results": "Résultats du sondage",
568569
"Poll sent": "Sondage envoyé",
570+
"Polls can't be scheduled": "Les sondages ne peuvent pas être programmés",
569571
"Previous": "Précédent",
570572
"Previous image": "Image précédente",
571573
"Putting on my thinking cap": "J'enfile mon bonnet de réflexion",
@@ -669,6 +671,7 @@
669671
"Thinking...": "Réflexion...",
670672
"this content could not be displayed": "ce contenu n'a pas pu être affiché",
671673
"This field cannot be empty or contain only spaces": "Ce champ ne peut pas être vide ou contenir uniquement des espaces",
674+
"This message can't be scheduled": "Ce message ne peut pas être programmé",
672675
"This message did not meet our content guidelines": "Ce message ne respecte pas nos directives de contenu",
673676
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
674677
"This user will be able to message you again.": "Cet utilisateur pourra à nouveau vous envoyer des messages.",

‎src/i18n/hi.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@
465465
"Location": "स्थान",
466466
"Location sharing ended": "स्थान साझा करना समाप्त",
467467
"Location: {{ coordinates }}": "स्थान: {{ coordinates }}",
468+
"Locations can't be scheduled": "स्थान शेड्यूल नहीं किए जा सकते",
468469
"Manage channel": "चैनल प्रबंधित करें",
469470
"Manage members": "सदस्य प्रबंधित करें",
470471
"Mark as unread": "अपठित चिह्नित करें",
@@ -547,6 +548,7 @@
547548
"Poll options": "मतदान विकल्प",
548549
"Poll results": "मतदान परिणाम",
549550
"Poll sent": "पोल भेजा गया",
551+
"Polls can't be scheduled": "पोल शेड्यूल नहीं किए जा सकते",
550552
"Previous": "पिछला",
551553
"Previous image": "पिछली छवि",
552554
"Putting on my thinking cap": "सोचने वाली टोपी पहन रहा हूँ",
@@ -645,6 +647,7 @@
645647
"Thinking...": "सोच रहा है...",
646648
"this content could not be displayed": "यह कॉन्टेंट लोड नहीं हो पाया",
647649
"This field cannot be empty or contain only spaces": "यह फ़ील्ड खाली नहीं हो सकता या केवल रिक्त स्थान नहीं रख सकता",
650+
"This message can't be scheduled": "यह संदेश शेड्यूल नहीं किया जा सकता",
648651
"This message did not meet our content guidelines": "यह संदेश हमारे सामग्री दिशानिर्देशों के अनुरूप नहीं था",
649652
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
650653
"This user will be able to message you again.": "यह उपयोगकर्ता आपको फिर से संदेश भेज सकेगा।",

‎src/i18n/it.json‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@
484484
"Location": "Posizione",
485485
"Location sharing ended": "Condivisione posizione terminata",
486486
"Location: {{ coordinates }}": "Posizione: {{ coordinates }}",
487+
"Locations can't be scheduled": "Le posizioni non possono essere programmate",
487488
"Manage channel": "Gestisci canale",
488489
"Manage members": "Gestisci membri",
489490
"Mark as unread": "Contrassegna come non letto",
@@ -566,6 +567,7 @@
566567
"Poll options": "Opzioni del sondaggio",
567568
"Poll results": "Risultati del sondaggio",
568569
"Poll sent": "Sondaggio inviato",
570+
"Polls can't be scheduled": "I sondaggi non possono essere programmati",
569571
"Previous": "Indietro",
570572
"Previous image": "Immagine precedente",
571573
"Putting on my thinking cap": "Mi metto il cappello del pensatore",
@@ -669,6 +671,7 @@
669671
"Thinking...": "Pensando...",
670672
"this content could not be displayed": "questo contenuto non può essere mostrato",
671673
"This field cannot be empty or contain only spaces": "Questo campo non può essere vuoto o contenere solo spazi",
674+
"This message can't be scheduled": "Questo messaggio non può essere programmato",
672675
"This message did not meet our content guidelines": "Questo messaggio non soddisfa le nostre linee guida sui contenuti",
673676
"This permanently deletes your message history with {{ user }}. This can't be undone.": "This permanently deletes your message history with {{ user }}. This can't be undone.",
674677
"This user will be able to message you again.": "Questo utente potrà inviarti di nuovo messaggi.",

0 commit comments

Comments
 (0)