@micha.bigler/ui-core-micha 2.41.2 → 2.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,118 +1,118 @@
1
1
  export const messagingTranslations = {
2
- 'MessagingComposer.ADD_EMOJI': { de: 'Emoji hinzufügen', en: 'Add emoji', fr: 'Ajouter un emoji' },
3
- 'MessagingComposer.EMOJI_PICKER': { de: 'Emoji auswählen', en: 'Choose an emoji', fr: 'Choisir un emoji' },
4
- 'MessagingComposer.STAGED_FILES': { de: 'Vorgemerkte Anhänge', en: 'Staged attachments', fr: 'Pièces jointes préparées' },
5
- 'MessagingComposer.REMOVE_ATTACHMENT': { de: '{{name}} entfernen', en: 'Remove {{name}}', fr: 'Supprimer {{name}}' },
6
- 'MessagingComposer.UPLOADING': { de: 'Anhänge werden hochgeladen…', en: 'Uploading attachments…', fr: 'Téléversement des pièces jointes…' },
7
- 'MessagingList.LABEL': { de: 'Unterhaltungen', en: 'Conversations', fr: 'Conversations' },
8
- 'MessagingList.EMPTY': { de: 'Noch keine Unterhaltungen.', en: 'No conversations yet.', fr: 'Aucune conversation pour le moment.' },
9
- 'MessagingList.NO_MESSAGES': { de: 'Noch keine Nachrichten', en: 'No messages yet', fr: 'Aucun message pour le moment' },
10
- 'MessagingList.UNTITLED': { de: 'Unbenannte Unterhaltung', en: 'Untitled conversation', fr: 'Conversation sans titre' },
11
- 'MessagingList.ACTIONS': { de: 'Aktionen für Unterhaltung', en: 'Conversation actions', fr: 'Actions de la conversation' },
12
- 'MessagingList.LOAD_MORE': { de: 'Mehr laden', en: 'Load more', fr: 'Charger plus' },
13
- 'MessagingList.LOAD_ERROR': { de: 'Unterhaltungen konnten nicht geladen werden.', en: 'Conversations could not be loaded.', fr: 'Impossible de charger les conversations.' },
14
- 'MessagingList.ARCHIVE': { de: 'Archivieren', en: 'Archive', fr: 'Archiver' },
15
- 'MessagingList.ARCHIVE_ERROR': { de: 'Unterhaltung konnte nicht archiviert werden.', en: 'Conversation could not be archived.', fr: 'Impossible d’archiver la conversation.' },
16
- 'MessagingList.MUTE': { de: 'Stummschalten', en: 'Mute', fr: 'Mettre en sourdine' },
17
- 'MessagingList.UNMUTE': { de: 'Stummschaltung aufheben', en: 'Unmute', fr: 'Réactiver le son' },
18
- 'MessagingList.PREFERENCES_ERROR': { de: 'Einstellungen konnten nicht gespeichert werden.', en: 'Preferences could not be saved.', fr: 'Impossible d’enregistrer les préférences.' },
19
- 'MessagingLaunchers.OPEN_GROUP': { de: 'Gruppenunterhaltung öffnen', en: 'Open group conversation', fr: 'Ouvrir la conversation de groupe' },
20
- 'MessagingLaunchers.OPEN_BROADCAST': { de: 'Ankündigungen öffnen', en: 'Open announcements', fr: 'Ouvrir les annonces' },
21
- 'MessagingLaunchers.OPEN_ERROR': { de: 'Unterhaltung konnte nicht geöffnet werden.', en: 'Conversation could not be opened.', fr: 'Impossible d’ouvrir la conversation.' },
22
- 'MessagingThread.TIMELINE': { de: 'Nachrichtenverlauf', en: 'Message timeline', fr: 'Chronologie des messages' },
23
- 'MessagingThread.MESSAGE': { de: 'Nachricht', en: 'Message', fr: 'Message' },
24
- 'MessagingThread.EMPTY': { de: 'Noch keine Nachrichten.', en: 'No messages yet.', fr: 'Aucun message pour le moment.' },
25
- 'MessagingThread.LOAD_OLDER': { de: 'Ältere Nachrichten laden', en: 'Load older messages', fr: 'Charger les messages plus anciens' },
26
- 'MessagingThread.LOAD_ERROR': { de: 'Nachrichten konnten nicht geladen werden.', en: 'Messages could not be loaded.', fr: 'Impossible de charger les messages.' },
27
- 'MessagingThread.REPLIES_ERROR': { de: 'Antworten konnten nicht geladen werden.', en: 'Replies could not be loaded.', fr: 'Impossible de charger les réponses.' },
28
- 'MessagingThread.DELETED': { de: 'Diese Nachricht wurde gelöscht.', en: 'This message was deleted.', fr: 'Ce message a été supprimé.' },
29
- 'MessagingThread.EDITED': { de: 'bearbeitet', en: 'edited', fr: 'modifié' },
30
- 'MessagingThread.REPLY': { de: 'Antworten', en: 'Reply', fr: 'Répondre' },
31
- 'MessagingThread.REPLY_TO': { de: 'Antwort auf {{sender}}', en: 'Reply to {{sender}}', fr: 'Réponse à {{sender}}' },
32
- 'MessagingThread.REPLYING_TO': { de: 'Antwort an {{sender}}', en: 'Replying to {{sender}}', fr: 'Réponse à {{sender}}' },
33
- 'MessagingThread.SHOW_REPLIES_one': { de: '{{count}} Antwort anzeigen', en: 'Show {{count}} reply', fr: 'Afficher {{count}} réponse' },
34
- 'MessagingThread.SHOW_REPLIES_other': { de: '{{count}} Antworten anzeigen', en: 'Show {{count}} replies', fr: 'Afficher {{count}} réponses' },
35
- 'MessagingThread.HIDE_REPLIES': { de: 'Antworten ausblenden', en: 'Hide replies', fr: 'Masquer les réponses' },
36
- 'MessagingThread.UNREAD_REPLIES': { de: 'Ungelesene Antworten', en: 'Unread replies', fr: 'Réponses non lues' },
37
- 'MessagingThread.UNKNOWN_SENDER': { de: 'Unbekannte Person', en: 'Unknown person', fr: 'Personne inconnue' },
38
- 'MessagingThread.QUOTE_ATTACHMENT': { de: 'Anhang', en: 'Attachment', fr: 'Pièce jointe' },
39
- 'MessagingActions.MENU': { de: 'Nachrichtenaktionen', en: 'Message actions', fr: 'Actions du message' },
40
- 'MessagingActions.EDIT': { de: 'Bearbeiten', en: 'Edit', fr: 'Modifier' },
41
- 'MessagingActions.SAVE': { de: 'Speichern', en: 'Save', fr: 'Enregistrer' },
42
- 'MessagingActions.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler' },
43
- 'MessagingActions.DELETE': { de: 'Löschen', en: 'Delete', fr: 'Supprimer' },
44
- 'MessagingActions.COPY': { de: 'Kopieren', en: 'Copy', fr: 'Copier' },
45
- 'MessagingActions.DELETE_CONFIRM_TITLE': { de: 'Nachricht löschen?', en: 'Delete message?', fr: 'Supprimer le message ?' },
46
- 'MessagingActions.DELETE_CONFIRM_BODY': { de: 'Diese Nachricht wird für alle entfernt.', en: 'This message will be removed for everyone.', fr: 'Ce message sera supprimé pour tout le monde.' },
47
- 'MessagingActions.EDIT_ERROR': { de: 'Nachricht konnte nicht bearbeitet werden: {{message}}', en: 'Message could not be edited: {{message}}', fr: 'Impossible de modifier le message : {{message}}' },
48
- 'MessagingActions.DELETE_ERROR': { de: 'Nachricht konnte nicht gelöscht werden: {{message}}', en: 'Message could not be deleted: {{message}}', fr: 'Impossible de supprimer le message : {{message}}' },
49
- 'MessagingActions.COPY_ERROR': { de: 'Nachricht konnte nicht kopiert werden: {{message}}', en: 'Message could not be copied: {{message}}', fr: 'Impossible de copier le message : {{message}}' },
50
- 'MessagingDirect.LAUNCH': { de: 'Direktnachricht starten', en: 'Start direct message', fr: 'Démarrer un message direct' },
51
- 'MessagingDirect.TITLE': { de: 'Direktnachricht starten', en: 'Start direct message', fr: 'Démarrer un message direct' },
52
- 'MessagingDirect.CANDIDATES': { de: 'Empfängerinnen und Empfänger', en: 'Recipients', fr: 'Destinataires' },
53
- 'MessagingDirect.EMPTY': { de: 'Keine Personen verfügbar.', en: 'No people are available.', fr: 'Aucune personne n’est disponible.' },
54
- 'MessagingDirect.START': { de: 'Starten', en: 'Start', fr: 'Démarrer' },
55
- 'MessagingDirect.STARTING': { de: 'Direktnachricht wird gestartet…', en: 'Starting direct message…', fr: 'Démarrage du message direct…' },
56
- 'MessagingDirect.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler' },
57
- 'MessagingDirect.START_ERROR': { de: 'Direktnachricht konnte nicht gestartet werden.', en: 'Direct message could not be started.', fr: 'Impossible de démarrer le message direct.' },
58
- 'MessagingReadTicks.ALL_READ': { de: 'Von allen gelesen', en: 'Read by everyone', fr: 'Lu par tout le monde' },
59
- 'MessagingReadTicks.SENT': { de: 'Gesendet', en: 'Sent', fr: 'Envoyé' },
60
- 'MessagingReadTicks.READ_RATIO': { de: '{{read}} von {{total}} gelesen', en: '{{read}} of {{total}} read', fr: '{{read}} sur {{total}} lu(s)' },
61
- 'MessagingReadTicks.RECIPIENTS': { de: 'Lesebestätigungen', en: 'Read recipients', fr: 'Destinataires lus' },
62
- 'MessagingComposer.LABEL': { de: 'Nachricht verfassen', en: 'Compose message', fr: 'Rédiger un message' },
63
- 'MessagingComposer.MESSAGE': { de: 'Nachricht', en: 'Message', fr: 'Message' },
64
- 'MessagingComposer.SEND': { de: 'Senden', en: 'Send', fr: 'Envoyer' },
65
- 'MessagingComposer.RETRY': { de: 'Erneut versuchen', en: 'Retry', fr: 'Réessayer' },
66
- 'MessagingComposer.ADD_ATTACHMENT': { de: 'Anhang hinzufügen', en: 'Add attachment', fr: 'Ajouter une pièce jointe' },
67
- 'MessagingComposer.FILES_SELECTED_one': { de: '{{count}} Anhang ausgewählt', en: '{{count}} attachment selected', fr: '{{count}} pièce jointe sélectionnée' },
68
- 'MessagingComposer.FILES_SELECTED_other': { de: '{{count}} Anhänge ausgewählt', en: '{{count}} attachments selected', fr: '{{count}} pièces jointes sélectionnées' },
69
- 'MessagingComposer.REPLYING_TO': { de: 'Antwort an {{sender}}', en: 'Replying to {{sender}}', fr: 'Réponse à {{sender}}' },
70
- 'MessagingComposer.SEND_ERROR': { de: 'Nachricht konnte nicht gesendet werden: {{message}}', en: 'Message could not be sent: {{message}}', fr: 'Impossible d’envoyer le message : {{message}}' },
71
- 'MessagingComposer.UPLOAD_ERROR': { de: 'Anhang wurde abgelehnt: {{message}}', en: 'Attachment was rejected: {{message}}', fr: 'La pièce jointe a été rejetée : {{message}}' },
72
- 'MessagingAttachments.LABEL': { de: 'Anhänge', en: 'Attachments', fr: 'Pièces jointes' },
73
- 'MessagingAttachments.DOWNLOAD': { de: '{{name}} herunterladen', en: 'Download {{name}}', fr: 'Télécharger {{name}}' },
74
- 'MessagingAttachments.PREVIEW': { de: '{{name}} als Vorschau öffnen', en: 'Preview {{name}}', fr: 'Prévisualiser {{name}}' },
75
- 'MessagingAttachments.CLOSE_PREVIEW': { de: 'Vorschau schliessen', en: 'Close preview', fr: 'Fermer l’aperçu' },
76
- 'MessagingAttachments.DOWNLOAD_ACTION': { de: 'Herunterladen', en: 'Download', fr: 'Télécharger' },
77
- 'MessagingAttachments.LOADING_PREVIEW': { de: 'Vorschau wird geladen', en: 'Loading preview', fr: 'Chargement de l’aperçu' },
78
- 'MessagingAttachments.PREVIEW_ERROR': { de: 'Vorschau konnte nicht geladen werden.', en: 'Preview could not be loaded.', fr: 'Impossible de charger l’aperçu.' },
79
- 'MessagingReactions.LABEL': { de: 'Reaktionen', en: 'Reactions', fr: 'Réactions' },
80
- 'MessagingReactions.ADD': { de: 'Reaktion hinzufügen', en: 'Add reaction', fr: 'Ajouter une réaction' },
81
- 'MessagingReactions.TOGGLE_one': { de: '{{emoji}} Reaktion mit {{count}} Stimme umschalten', en: 'Toggle {{emoji}} reaction with {{count}} vote', fr: 'Basculer la réaction {{emoji}} avec {{count}} vote' },
82
- 'MessagingReactions.TOGGLE_other': { de: '{{emoji}} Reaktion mit {{count}} Stimmen umschalten', en: 'Toggle {{emoji}} reaction with {{count}} votes', fr: 'Basculer la réaction {{emoji}} avec {{count}} votes' },
83
- 'MessagingReactions.ERROR': { de: 'Reaktion konnte nicht gespeichert werden: {{message}}', en: 'Reaction could not be saved: {{message}}', fr: 'Impossible d’enregistrer la réaction : {{message}}' },
84
- 'MessagingPoll.LABEL': { de: 'Umfrage', en: 'Poll', fr: 'Sondage' },
85
- 'MessagingPoll.CLOSE': { de: 'Umfrage schliessen', en: 'Close poll', fr: 'Clore le sondage' },
86
- 'MessagingPoll.CLOSED': { de: 'Geschlossen', en: 'Closed', fr: 'Clos' },
87
- 'MessagingPoll.OPTION_RESULT': { de: '{{count}} ({{percent}} %)', en: '{{count}} ({{percent}}%)', fr: '{{count}} ({{percent}} %)' },
88
- 'MessagingPoll.VOTE_ERROR': { de: 'Stimme konnte nicht gespeichert werden: {{message}}', en: 'Vote could not be saved: {{message}}', fr: 'Impossible d’enregistrer le vote : {{message}}' },
89
- 'MessagingPoll.CLOSE_ERROR': { de: 'Umfrage konnte nicht geschlossen werden: {{message}}', en: 'Poll could not be closed: {{message}}', fr: 'Impossible de clore le sondage : {{message}}' },
90
- 'MessagingPoll.CREATE': { de: 'Umfrage erstellen', en: 'Create poll', fr: 'Créer un sondage' },
91
- 'MessagingPoll.CREATE_ERROR': { de: 'Umfrage konnte nicht erstellt werden: {{message}}', en: 'Poll could not be created: {{message}}', fr: 'Impossible de créer le sondage : {{message}}' },
92
- 'MessagingPoll.CREATE_VALIDATION': { de: 'Frage und mindestens zwei Optionen sind erforderlich.', en: 'A question and at least two options are required.', fr: 'Une question et au moins deux options sont requises.' },
93
- 'MessagingPoll.QUESTION': { de: 'Frage', en: 'Question', fr: 'Question' },
94
- 'MessagingPoll.OPTION': { de: 'Option {{count}}', en: 'Option {{count}}', fr: 'Option {{count}}' },
95
- 'MessagingPoll.ADD_OPTION': { de: 'Option hinzufügen', en: 'Add option', fr: 'Ajouter une option' },
96
- 'MessagingPoll.ALLOW_MULTIPLE': { de: 'Mehrfachauswahl erlauben', en: 'Allow multiple choices', fr: 'Autoriser plusieurs choix' },
97
- 'MessagingPoll.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler' },
98
- 'MessagingPoll.YOU_VOTED': { de: 'von dir gewählt', en: 'voted by you', fr: 'voté par vous' },
99
- 'MessagingConfig.LABEL': { de: 'Nachrichten-Einstellungen', en: 'Messaging settings', fr: 'Paramètres de messagerie' },
100
- 'MessagingConfig.TITLE': { de: 'Nachrichten-Einstellungen', en: 'Messaging settings', fr: 'Paramètres de messagerie' },
101
- 'MessagingConfig.LOADING': { de: 'Einstellungen werden geladen…', en: 'Loading settings…', fr: 'Chargement des paramètres…' },
102
- 'MessagingConfig.LOAD_ERROR': { de: 'Einstellungen konnten nicht geladen werden: {{message}}', en: 'Settings could not be loaded: {{message}}', fr: 'Impossible de charger les paramètres : {{message}}' },
103
- 'MessagingConfig.SAVE_ERROR': { de: 'Einstellungen konnten nicht gespeichert werden: {{message}}', en: 'Settings could not be saved: {{message}}', fr: 'Impossible d’enregistrer les paramètres : {{message}}' },
104
- 'MessagingConfig.DM_POLICY': { de: 'Direktnachrichten-Regel', en: 'Direct-message policy', fr: 'Règle des messages directs' },
105
- 'MessagingConfig.DM_ALL': { de: 'Alle', en: 'Everyone', fr: 'Tout le monde' },
106
- 'MessagingConfig.DM_SHARED': { de: 'Nur gemeinsame Gruppen', en: 'Shared groups only', fr: 'Groupes communs uniquement' },
107
- 'MessagingConfig.DM_TEAM': { de: 'Nur Team', en: 'Team only', fr: 'Équipe uniquement' },
108
- 'MessagingConfig.GROUP_ENABLED': { de: 'Gruppenchat aktivieren', en: 'Enable group chat', fr: 'Activer le chat de groupe' },
109
- 'MessagingConfig.EVERYONE_POSTS': { de: 'Alle dürfen schreiben', en: 'Everyone can post', fr: 'Tout le monde peut publier' },
110
- 'MessagingAnnouncement.CREATE': { de: 'Ankündigung erstellen', en: 'Create announcement', fr: 'Créer une annonce' },
111
- 'MessagingAnnouncement.TITLE': { de: 'Titel', en: 'Title', fr: 'Titre' },
112
- 'MessagingAnnouncement.BODY': { de: 'Text', en: 'Body', fr: 'Texte' },
113
- 'MessagingAnnouncement.SEND': { de: 'Ankündigung senden', en: 'Send announcement', fr: 'Envoyer l’annonce' },
114
- 'MessagingAnnouncement.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler' },
115
- 'MessagingAnnouncement.VALIDATION': { de: 'Ein Titel ist erforderlich.', en: 'A title is required.', fr: 'Un titre est requis.' },
116
- 'MessagingAnnouncement.ERROR': { de: 'Ankündigung konnte nicht gesendet werden: {{message}}', en: 'Announcement could not be sent: {{message}}', fr: 'Impossible d’envoyer l’annonce : {{message}}' },
117
- 'MessagingAnnouncement.OPEN_LINK': { de: 'Link öffnen', en: 'Open link', fr: 'Ouvrir le lien' },
2
+ 'MessagingComposer.ADD_EMOJI': { de: 'Emoji hinzufügen', en: 'Add emoji', fr: 'Ajouter un emoji', sw: 'Ongeza emoji' },
3
+ 'MessagingComposer.EMOJI_PICKER': { de: 'Emoji auswählen', en: 'Choose an emoji', fr: 'Choisir un emoji', sw: 'Chagua emoji' },
4
+ 'MessagingComposer.STAGED_FILES': { de: 'Vorgemerkte Anhänge', en: 'Staged attachments', fr: 'Pièces jointes préparées', sw: 'Viambatisho vilivyoandaliwa' },
5
+ 'MessagingComposer.REMOVE_ATTACHMENT': { de: '{{name}} entfernen', en: 'Remove {{name}}', fr: 'Supprimer {{name}}', sw: 'Ondoa {{name}}' },
6
+ 'MessagingComposer.UPLOADING': { de: 'Anhänge werden hochgeladen…', en: 'Uploading attachments…', fr: 'Téléversement des pièces jointes…', sw: 'Inapakia viambatisho…' },
7
+ 'MessagingList.LABEL': { de: 'Unterhaltungen', en: 'Conversations', fr: 'Conversations', sw: 'Mazungumzo' },
8
+ 'MessagingList.EMPTY': { de: 'Noch keine Unterhaltungen.', en: 'No conversations yet.', fr: 'Aucune conversation pour le moment.', sw: 'Bado hakuna mazungumzo.' },
9
+ 'MessagingList.NO_MESSAGES': { de: 'Noch keine Nachrichten', en: 'No messages yet', fr: 'Aucun message pour le moment', sw: 'Bado hakuna ujumbe' },
10
+ 'MessagingList.UNTITLED': { de: 'Unbenannte Unterhaltung', en: 'Untitled conversation', fr: 'Conversation sans titre', sw: 'Mazungumzo yasiyo na kichwa' },
11
+ 'MessagingList.ACTIONS': { de: 'Aktionen für Unterhaltung', en: 'Conversation actions', fr: 'Actions de la conversation', sw: 'Vitendo vya mazungumzo' },
12
+ 'MessagingList.LOAD_MORE': { de: 'Mehr laden', en: 'Load more', fr: 'Charger plus', sw: 'Pakia zaidi' },
13
+ 'MessagingList.LOAD_ERROR': { de: 'Unterhaltungen konnten nicht geladen werden.', en: 'Conversations could not be loaded.', fr: 'Impossible de charger les conversations.', sw: 'Mazungumzo hayakuweza kupakiwa.' },
14
+ 'MessagingList.ARCHIVE': { de: 'Archivieren', en: 'Archive', fr: 'Archiver', sw: 'Weka kwenye kumbukumbu' },
15
+ 'MessagingList.ARCHIVE_ERROR': { de: 'Unterhaltung konnte nicht archiviert werden.', en: 'Conversation could not be archived.', fr: 'Impossible d’archiver la conversation.', sw: 'Mazungumzo hayakuweza kuwekwa kwenye kumbukumbu.' },
16
+ 'MessagingList.MUTE': { de: 'Stummschalten', en: 'Mute', fr: 'Mettre en sourdine', sw: 'Nyamazisha' },
17
+ 'MessagingList.UNMUTE': { de: 'Stummschaltung aufheben', en: 'Unmute', fr: 'Réactiver le son', sw: 'Ondoa unyamazishaji' },
18
+ 'MessagingList.PREFERENCES_ERROR': { de: 'Einstellungen konnten nicht gespeichert werden.', en: 'Preferences could not be saved.', fr: 'Impossible d’enregistrer les préférences.', sw: 'Mapendeleo hayakuweza kuhifadhiwa.' },
19
+ 'MessagingLaunchers.OPEN_GROUP': { de: 'Gruppenunterhaltung öffnen', en: 'Open group conversation', fr: 'Ouvrir la conversation de groupe', sw: 'Fungua mazungumzo ya kikundi' },
20
+ 'MessagingLaunchers.OPEN_BROADCAST': { de: 'Ankündigungen öffnen', en: 'Open announcements', fr: 'Ouvrir les annonces', sw: 'Fungua matangazo' },
21
+ 'MessagingLaunchers.OPEN_ERROR': { de: 'Unterhaltung konnte nicht geöffnet werden.', en: 'Conversation could not be opened.', fr: 'Impossible d’ouvrir la conversation.', sw: 'Mazungumzo hayakuweza kufunguliwa.' },
22
+ 'MessagingThread.TIMELINE': { de: 'Nachrichtenverlauf', en: 'Message timeline', fr: 'Chronologie des messages', sw: 'Mfuatano wa ujumbe' },
23
+ 'MessagingThread.MESSAGE': { de: 'Nachricht', en: 'Message', fr: 'Message', sw: 'Ujumbe' },
24
+ 'MessagingThread.EMPTY': { de: 'Noch keine Nachrichten.', en: 'No messages yet.', fr: 'Aucun message pour le moment.', sw: 'Bado hakuna ujumbe.' },
25
+ 'MessagingThread.LOAD_OLDER': { de: 'Ältere Nachrichten laden', en: 'Load older messages', fr: 'Charger les messages plus anciens', sw: 'Pakia ujumbe wa zamani' },
26
+ 'MessagingThread.LOAD_ERROR': { de: 'Nachrichten konnten nicht geladen werden.', en: 'Messages could not be loaded.', fr: 'Impossible de charger les messages.', sw: 'Ujumbe haukuweza kupakiwa.' },
27
+ 'MessagingThread.REPLIES_ERROR': { de: 'Antworten konnten nicht geladen werden.', en: 'Replies could not be loaded.', fr: 'Impossible de charger les réponses.', sw: 'Majibu hayakuweza kupakiwa.' },
28
+ 'MessagingThread.DELETED': { de: 'Diese Nachricht wurde gelöscht.', en: 'This message was deleted.', fr: 'Ce message a été supprimé.', sw: 'Ujumbe huu ulifutwa.' },
29
+ 'MessagingThread.EDITED': { de: 'bearbeitet', en: 'edited', fr: 'modifié', sw: 'umehaririwa' },
30
+ 'MessagingThread.REPLY': { de: 'Antworten', en: 'Reply', fr: 'Répondre', sw: 'Jibu' },
31
+ 'MessagingThread.REPLY_TO': { de: 'Antwort auf {{sender}}', en: 'Reply to {{sender}}', fr: 'Réponse à {{sender}}', sw: 'Jibu kwa {{sender}}' },
32
+ 'MessagingThread.REPLYING_TO': { de: 'Antwort an {{sender}}', en: 'Replying to {{sender}}', fr: 'Réponse à {{sender}}', sw: 'Unamjibu {{sender}}' },
33
+ 'MessagingThread.SHOW_REPLIES_one': { de: '{{count}} Antwort anzeigen', en: 'Show {{count}} reply', fr: 'Afficher {{count}} réponse', sw: 'Onyesha jibu {{count}}' },
34
+ 'MessagingThread.SHOW_REPLIES_other': { de: '{{count}} Antworten anzeigen', en: 'Show {{count}} replies', fr: 'Afficher {{count}} réponses', sw: 'Onyesha majibu {{count}}' },
35
+ 'MessagingThread.HIDE_REPLIES': { de: 'Antworten ausblenden', en: 'Hide replies', fr: 'Masquer les réponses', sw: 'Ficha majibu' },
36
+ 'MessagingThread.UNREAD_REPLIES': { de: 'Ungelesene Antworten', en: 'Unread replies', fr: 'Réponses non lues', sw: 'Majibu ambayo hayajasomwa' },
37
+ 'MessagingThread.UNKNOWN_SENDER': { de: 'Unbekannte Person', en: 'Unknown person', fr: 'Personne inconnue', sw: 'Mtu asiyejulikana' },
38
+ 'MessagingThread.QUOTE_ATTACHMENT': { de: 'Anhang', en: 'Attachment', fr: 'Pièce jointe', sw: 'Kiambatisho' },
39
+ 'MessagingActions.MENU': { de: 'Nachrichtenaktionen', en: 'Message actions', fr: 'Actions du message', sw: 'Vitendo vya ujumbe' },
40
+ 'MessagingActions.EDIT': { de: 'Bearbeiten', en: 'Edit', fr: 'Modifier', sw: 'Hariri' },
41
+ 'MessagingActions.SAVE': { de: 'Speichern', en: 'Save', fr: 'Enregistrer', sw: 'Hifadhi' },
42
+ 'MessagingActions.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler', sw: 'Ghairi' },
43
+ 'MessagingActions.DELETE': { de: 'Löschen', en: 'Delete', fr: 'Supprimer', sw: 'Futa' },
44
+ 'MessagingActions.COPY': { de: 'Kopieren', en: 'Copy', fr: 'Copier', sw: 'Nakili' },
45
+ 'MessagingActions.DELETE_CONFIRM_TITLE': { de: 'Nachricht löschen?', en: 'Delete message?', fr: 'Supprimer le message ?', sw: 'Ufute ujumbe?' },
46
+ 'MessagingActions.DELETE_CONFIRM_BODY': { de: 'Diese Nachricht wird für alle entfernt.', en: 'This message will be removed for everyone.', fr: 'Ce message sera supprimé pour tout le monde.', sw: 'Ujumbe huu utaondolewa kwa kila mtu.' },
47
+ 'MessagingActions.EDIT_ERROR': { de: 'Nachricht konnte nicht bearbeitet werden: {{message}}', en: 'Message could not be edited: {{message}}', fr: 'Impossible de modifier le message : {{message}}', sw: 'Ujumbe haukuweza kuhaririwa: {{message}}' },
48
+ 'MessagingActions.DELETE_ERROR': { de: 'Nachricht konnte nicht gelöscht werden: {{message}}', en: 'Message could not be deleted: {{message}}', fr: 'Impossible de supprimer le message : {{message}}', sw: 'Ujumbe haukuweza kufutwa: {{message}}' },
49
+ 'MessagingActions.COPY_ERROR': { de: 'Nachricht konnte nicht kopiert werden: {{message}}', en: 'Message could not be copied: {{message}}', fr: 'Impossible de copier le message : {{message}}', sw: 'Ujumbe haukuweza kunakiliwa: {{message}}' },
50
+ 'MessagingDirect.LAUNCH': { de: 'Direktnachricht starten', en: 'Start direct message', fr: 'Démarrer un message direct', sw: 'Anza ujumbe wa moja kwa moja' },
51
+ 'MessagingDirect.TITLE': { de: 'Direktnachricht starten', en: 'Start direct message', fr: 'Démarrer un message direct', sw: 'Anza ujumbe wa moja kwa moja' },
52
+ 'MessagingDirect.CANDIDATES': { de: 'Empfängerinnen und Empfänger', en: 'Recipients', fr: 'Destinataires', sw: 'Wapokeaji' },
53
+ 'MessagingDirect.EMPTY': { de: 'Keine Personen verfügbar.', en: 'No people are available.', fr: 'Aucune personne n’est disponible.', sw: 'Hakuna watu wanaopatikana.' },
54
+ 'MessagingDirect.START': { de: 'Starten', en: 'Start', fr: 'Démarrer', sw: 'Anza' },
55
+ 'MessagingDirect.STARTING': { de: 'Direktnachricht wird gestartet…', en: 'Starting direct message…', fr: 'Démarrage du message direct…', sw: 'Inaanzisha ujumbe wa moja kwa moja…' },
56
+ 'MessagingDirect.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler', sw: 'Ghairi' },
57
+ 'MessagingDirect.START_ERROR': { de: 'Direktnachricht konnte nicht gestartet werden.', en: 'Direct message could not be started.', fr: 'Impossible de démarrer le message direct.', sw: 'Ujumbe wa moja kwa moja haukuweza kuanzishwa.' },
58
+ 'MessagingReadTicks.ALL_READ': { de: 'Von allen gelesen', en: 'Read by everyone', fr: 'Lu par tout le monde', sw: 'Wote wamesoma' },
59
+ 'MessagingReadTicks.SENT': { de: 'Gesendet', en: 'Sent', fr: 'Envoyé', sw: 'Umetumwa' },
60
+ 'MessagingReadTicks.READ_RATIO': { de: '{{read}} von {{total}} gelesen', en: '{{read}} of {{total}} read', fr: '{{read}} sur {{total}} lu(s)', sw: '{{read}} kati ya {{total}} wamesoma' },
61
+ 'MessagingReadTicks.RECIPIENTS': { de: 'Lesebestätigungen', en: 'Read recipients', fr: 'Destinataires lus', sw: 'Wapokeaji waliosoma' },
62
+ 'MessagingComposer.LABEL': { de: 'Nachricht verfassen', en: 'Compose message', fr: 'Rédiger un message', sw: 'Andika ujumbe' },
63
+ 'MessagingComposer.MESSAGE': { de: 'Nachricht', en: 'Message', fr: 'Message', sw: 'Ujumbe' },
64
+ 'MessagingComposer.SEND': { de: 'Senden', en: 'Send', fr: 'Envoyer', sw: 'Tuma' },
65
+ 'MessagingComposer.RETRY': { de: 'Erneut versuchen', en: 'Retry', fr: 'Réessayer', sw: 'Jaribu tena' },
66
+ 'MessagingComposer.ADD_ATTACHMENT': { de: 'Anhang hinzufügen', en: 'Add attachment', fr: 'Ajouter une pièce jointe', sw: 'Ongeza kiambatisho' },
67
+ 'MessagingComposer.FILES_SELECTED_one': { de: '{{count}} Anhang ausgewählt', en: '{{count}} attachment selected', fr: '{{count}} pièce jointe sélectionnée', sw: 'Kiambatisho {{count}} kimechaguliwa' },
68
+ 'MessagingComposer.FILES_SELECTED_other': { de: '{{count}} Anhänge ausgewählt', en: '{{count}} attachments selected', fr: '{{count}} pièces jointes sélectionnées', sw: 'Viambatisho {{count}} vimechaguliwa' },
69
+ 'MessagingComposer.REPLYING_TO': { de: 'Antwort an {{sender}}', en: 'Replying to {{sender}}', fr: 'Réponse à {{sender}}', sw: 'Unamjibu {{sender}}' },
70
+ 'MessagingComposer.SEND_ERROR': { de: 'Nachricht konnte nicht gesendet werden: {{message}}', en: 'Message could not be sent: {{message}}', fr: 'Impossible d’envoyer le message : {{message}}', sw: 'Ujumbe haukuweza kutumwa: {{message}}' },
71
+ 'MessagingComposer.UPLOAD_ERROR': { de: 'Anhang wurde abgelehnt: {{message}}', en: 'Attachment was rejected: {{message}}', fr: 'La pièce jointe a été rejetée : {{message}}', sw: 'Kiambatisho kilikataliwa: {{message}}' },
72
+ 'MessagingAttachments.LABEL': { de: 'Anhänge', en: 'Attachments', fr: 'Pièces jointes', sw: 'Viambatisho' },
73
+ 'MessagingAttachments.DOWNLOAD': { de: '{{name}} herunterladen', en: 'Download {{name}}', fr: 'Télécharger {{name}}', sw: 'Pakua {{name}}' },
74
+ 'MessagingAttachments.PREVIEW': { de: '{{name}} als Vorschau öffnen', en: 'Preview {{name}}', fr: 'Prévisualiser {{name}}', sw: 'Kagua {{name}}' },
75
+ 'MessagingAttachments.CLOSE_PREVIEW': { de: 'Vorschau schliessen', en: 'Close preview', fr: 'Fermer l’aperçu', sw: 'Funga onyesho la kukagua' },
76
+ 'MessagingAttachments.DOWNLOAD_ACTION': { de: 'Herunterladen', en: 'Download', fr: 'Télécharger', sw: 'Pakua' },
77
+ 'MessagingAttachments.LOADING_PREVIEW': { de: 'Vorschau wird geladen', en: 'Loading preview', fr: 'Chargement de l’aperçu', sw: 'Inapakia onyesho la kukagua' },
78
+ 'MessagingAttachments.PREVIEW_ERROR': { de: 'Vorschau konnte nicht geladen werden.', en: 'Preview could not be loaded.', fr: 'Impossible de charger l’aperçu.', sw: 'Onyesho la kukagua halikuweza kupakiwa.' },
79
+ 'MessagingReactions.LABEL': { de: 'Reaktionen', en: 'Reactions', fr: 'Réactions', sw: 'Miitikio' },
80
+ 'MessagingReactions.ADD': { de: 'Reaktion hinzufügen', en: 'Add reaction', fr: 'Ajouter une réaction', sw: 'Ongeza mwitikio' },
81
+ 'MessagingReactions.TOGGLE_one': { de: '{{emoji}} Reaktion mit {{count}} Stimme umschalten', en: 'Toggle {{emoji}} reaction with {{count}} vote', fr: 'Basculer la réaction {{emoji}} avec {{count}} vote', sw: 'Badilisha mwitikio wa {{emoji}} wenye kura {{count}}' },
82
+ 'MessagingReactions.TOGGLE_other': { de: '{{emoji}} Reaktion mit {{count}} Stimmen umschalten', en: 'Toggle {{emoji}} reaction with {{count}} votes', fr: 'Basculer la réaction {{emoji}} avec {{count}} votes', sw: 'Badilisha mwitikio wa {{emoji}} wenye kura {{count}}' },
83
+ 'MessagingReactions.ERROR': { de: 'Reaktion konnte nicht gespeichert werden: {{message}}', en: 'Reaction could not be saved: {{message}}', fr: 'Impossible d’enregistrer la réaction : {{message}}', sw: 'Mwitikio haukuweza kuhifadhiwa: {{message}}' },
84
+ 'MessagingPoll.LABEL': { de: 'Umfrage', en: 'Poll', fr: 'Sondage', sw: 'Kura ya maoni' },
85
+ 'MessagingPoll.CLOSE': { de: 'Umfrage schliessen', en: 'Close poll', fr: 'Clore le sondage', sw: 'Funga kura ya maoni' },
86
+ 'MessagingPoll.CLOSED': { de: 'Geschlossen', en: 'Closed', fr: 'Clos', sw: 'Imefungwa' },
87
+ 'MessagingPoll.OPTION_RESULT': { de: '{{count}} ({{percent}} %)', en: '{{count}} ({{percent}}%)', fr: '{{count}} ({{percent}} %)', sw: '{{count}} ({{percent}}%)' },
88
+ 'MessagingPoll.VOTE_ERROR': { de: 'Stimme konnte nicht gespeichert werden: {{message}}', en: 'Vote could not be saved: {{message}}', fr: 'Impossible d’enregistrer le vote : {{message}}', sw: 'Kura haikuweza kuhifadhiwa: {{message}}' },
89
+ 'MessagingPoll.CLOSE_ERROR': { de: 'Umfrage konnte nicht geschlossen werden: {{message}}', en: 'Poll could not be closed: {{message}}', fr: 'Impossible de clore le sondage : {{message}}', sw: 'Kura ya maoni haikuweza kufungwa: {{message}}' },
90
+ 'MessagingPoll.CREATE': { de: 'Umfrage erstellen', en: 'Create poll', fr: 'Créer un sondage', sw: 'Unda kura ya maoni' },
91
+ 'MessagingPoll.CREATE_ERROR': { de: 'Umfrage konnte nicht erstellt werden: {{message}}', en: 'Poll could not be created: {{message}}', fr: 'Impossible de créer le sondage : {{message}}', sw: 'Kura ya maoni haikuweza kuundwa: {{message}}' },
92
+ 'MessagingPoll.CREATE_VALIDATION': { de: 'Frage und mindestens zwei Optionen sind erforderlich.', en: 'A question and at least two options are required.', fr: 'Une question et au moins deux options sont requises.', sw: 'Swali na angalau chaguo mbili vinahitajika.' },
93
+ 'MessagingPoll.QUESTION': { de: 'Frage', en: 'Question', fr: 'Question', sw: 'Swali' },
94
+ 'MessagingPoll.OPTION': { de: 'Option {{count}}', en: 'Option {{count}}', fr: 'Option {{count}}', sw: 'Chaguo {{count}}' },
95
+ 'MessagingPoll.ADD_OPTION': { de: 'Option hinzufügen', en: 'Add option', fr: 'Ajouter une option', sw: 'Ongeza chaguo' },
96
+ 'MessagingPoll.ALLOW_MULTIPLE': { de: 'Mehrfachauswahl erlauben', en: 'Allow multiple choices', fr: 'Autoriser plusieurs choix', sw: 'Ruhusu chaguo nyingi' },
97
+ 'MessagingPoll.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler', sw: 'Ghairi' },
98
+ 'MessagingPoll.YOU_VOTED': { de: 'von dir gewählt', en: 'voted by you', fr: 'voté par vous', sw: 'ulichagua' },
99
+ 'MessagingConfig.LABEL': { de: 'Nachrichten-Einstellungen', en: 'Messaging settings', fr: 'Paramètres de messagerie', sw: 'Mipangilio ya ujumbe' },
100
+ 'MessagingConfig.TITLE': { de: 'Nachrichten-Einstellungen', en: 'Messaging settings', fr: 'Paramètres de messagerie', sw: 'Mipangilio ya ujumbe' },
101
+ 'MessagingConfig.LOADING': { de: 'Einstellungen werden geladen…', en: 'Loading settings…', fr: 'Chargement des paramètres…', sw: 'Inapakia mipangilio…' },
102
+ 'MessagingConfig.LOAD_ERROR': { de: 'Einstellungen konnten nicht geladen werden: {{message}}', en: 'Settings could not be loaded: {{message}}', fr: 'Impossible de charger les paramètres : {{message}}', sw: 'Mipangilio haikuweza kupakiwa: {{message}}' },
103
+ 'MessagingConfig.SAVE_ERROR': { de: 'Einstellungen konnten nicht gespeichert werden: {{message}}', en: 'Settings could not be saved: {{message}}', fr: 'Impossible d’enregistrer les paramètres : {{message}}', sw: 'Mipangilio haikuweza kuhifadhiwa: {{message}}' },
104
+ 'MessagingConfig.DM_POLICY': { de: 'Direktnachrichten-Regel', en: 'Direct-message policy', fr: 'Règle des messages directs', sw: 'Sera ya ujumbe wa moja kwa moja' },
105
+ 'MessagingConfig.DM_ALL': { de: 'Alle', en: 'Everyone', fr: 'Tout le monde', sw: 'Kila mtu' },
106
+ 'MessagingConfig.DM_SHARED': { de: 'Nur gemeinsame Gruppen', en: 'Shared groups only', fr: 'Groupes communs uniquement', sw: 'Vikundi vya pamoja pekee' },
107
+ 'MessagingConfig.DM_TEAM': { de: 'Nur Team', en: 'Team only', fr: 'Équipe uniquement', sw: 'Timu pekee' },
108
+ 'MessagingConfig.GROUP_ENABLED': { de: 'Gruppenchat aktivieren', en: 'Enable group chat', fr: 'Activer le chat de groupe', sw: 'Washa gumzo la kikundi' },
109
+ 'MessagingConfig.EVERYONE_POSTS': { de: 'Alle dürfen schreiben', en: 'Everyone can post', fr: 'Tout le monde peut publier', sw: 'Kila mtu anaweza kutuma ujumbe' },
110
+ 'MessagingAnnouncement.CREATE': { de: 'Ankündigung erstellen', en: 'Create announcement', fr: 'Créer une annonce', sw: 'Unda tangazo' },
111
+ 'MessagingAnnouncement.TITLE': { de: 'Titel', en: 'Title', fr: 'Titre', sw: 'Kichwa' },
112
+ 'MessagingAnnouncement.BODY': { de: 'Text', en: 'Body', fr: 'Texte', sw: 'Maandishi' },
113
+ 'MessagingAnnouncement.SEND': { de: 'Ankündigung senden', en: 'Send announcement', fr: 'Envoyer l’annonce', sw: 'Tuma tangazo' },
114
+ 'MessagingAnnouncement.CANCEL': { de: 'Abbrechen', en: 'Cancel', fr: 'Annuler', sw: 'Ghairi' },
115
+ 'MessagingAnnouncement.VALIDATION': { de: 'Ein Titel ist erforderlich.', en: 'A title is required.', fr: 'Un titre est requis.', sw: 'Kichwa kinahitajika.' },
116
+ 'MessagingAnnouncement.ERROR': { de: 'Ankündigung konnte nicht gesendet werden: {{message}}', en: 'Announcement could not be sent: {{message}}', fr: 'Impossible d’envoyer l’annonce : {{message}}', sw: 'Tangazo halikuweza kutumwa: {{message}}' },
117
+ 'MessagingAnnouncement.OPEN_LINK': { de: 'Link öffnen', en: 'Open link', fr: 'Ouvrir le lien', sw: 'Fungua kiungo' },
118
118
  };
@@ -71,4 +71,52 @@ describe('BarChart preset', () => {
71
71
  expect(props.xAxis[0].label).toBeUndefined();
72
72
  expect(props.yAxis[0].label).toBeUndefined();
73
73
  });
74
+
75
+ // CHART-8: minHeight/height/aspect resolution, wired through the actual component.
76
+ describe('minHeight/height resolution (CHART-8)', () => {
77
+ it('sizes the chart from minHeight alone when neither height nor aspect is set', () => {
78
+ renderChart({ series: [{ data: [1] }], minHeight: 300 });
79
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(300);
80
+ expect(window.getComputedStyle(screen.getByTestId('bar-chart-container')).minHeight).toBe('300px');
81
+ });
82
+
83
+ it('leaves minHeight as a floor and gives the chart no fixed height when aspect is set (no height)', () => {
84
+ renderChart({ series: [{ data: [1] }], minHeight: 320, aspect: 1.8 });
85
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBeUndefined();
86
+ const style = window.getComputedStyle(screen.getByTestId('bar-chart-container'));
87
+ expect(style.minHeight).toBe('320px');
88
+ expect(style.aspectRatio).toBe('1.8 / 1');
89
+ });
90
+
91
+ it('caps the wrapper at height when minHeight is larger, closing the dead-space gap', () => {
92
+ renderChart({ series: [{ data: [1] }], minHeight: 420, height: 380 });
93
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(380);
94
+ expect(window.getComputedStyle(screen.getByTestId('bar-chart-container')).minHeight).toBe('380px');
95
+ });
96
+
97
+ it('is byte-identical when minHeight equals height', () => {
98
+ renderChart({ series: [{ data: [1] }], minHeight: 320, height: 320 });
99
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(320);
100
+ expect(window.getComputedStyle(screen.getByTestId('bar-chart-container')).minHeight).toBe('320px');
101
+ });
102
+
103
+ it('is unchanged when height is passed alone', () => {
104
+ renderChart({ series: [{ data: [1] }], height: 280 });
105
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(280);
106
+ expect(window.getComputedStyle(screen.getByTestId('bar-chart-container')).minHeight).toBe('auto');
107
+ });
108
+
109
+ it('warns only on the disagreeing pair, naming both values, and not on the aspect combination', () => {
110
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
111
+ renderChart({ series: [{ data: [1] }], minHeight: 420, height: 380 });
112
+ expect(warn).toHaveBeenCalledOnce();
113
+ expect(warn.mock.calls[0][0]).toContain('420');
114
+ expect(warn.mock.calls[0][0]).toContain('380');
115
+ warn.mockClear();
116
+
117
+ renderChart({ series: [{ data: [1] }], minHeight: 320, aspect: 1.8 });
118
+ expect(warn).not.toHaveBeenCalled();
119
+ warn.mockRestore();
120
+ });
121
+ });
74
122
  });
@@ -211,4 +211,47 @@ describe('ChartFrame', () => {
211
211
  renderFrame({ isEmpty: true }, 'fr');
212
212
  expect(screen.getByText('Aucune donnée disponible.')).toBeTruthy();
213
213
  });
214
+
215
+ // CHART-8: minHeight/height/aspect resolution on ChartFrame's own content box.
216
+ describe('minHeight/height resolution (CHART-8)', () => {
217
+ function contentBoxStyle() {
218
+ return window.getComputedStyle(screen.getByTestId('chart-body').parentElement);
219
+ }
220
+
221
+ it('sizes the content box from minHeight alone when neither height nor aspect is set', () => {
222
+ renderFrame({ minHeight: 300 });
223
+ const style = contentBoxStyle();
224
+ expect(style.minHeight).toBe('300px');
225
+ expect(style.height).toBe('300px');
226
+ });
227
+
228
+ it('leaves minHeight as a floor and gives no fixed height when aspect is set (no height)', () => {
229
+ renderFrame({ minHeight: 320, aspect: 1.8 });
230
+ const style = contentBoxStyle();
231
+ expect(style.minHeight).toBe('320px');
232
+ expect(style.height).toBe('auto');
233
+ expect(style.aspectRatio).toBe('1.8 / 1');
234
+ });
235
+
236
+ it('caps the wrapper at height when minHeight is larger, closing the dead-space gap', () => {
237
+ renderFrame({ minHeight: 420, height: 380 });
238
+ const style = contentBoxStyle();
239
+ expect(style.minHeight).toBe('380px');
240
+ expect(style.height).toBe('380px');
241
+ });
242
+
243
+ it('is byte-identical when minHeight equals height', () => {
244
+ renderFrame({ minHeight: 320, height: 320 });
245
+ const style = contentBoxStyle();
246
+ expect(style.minHeight).toBe('320px');
247
+ expect(style.height).toBe('320px');
248
+ });
249
+
250
+ it('is unchanged when height is passed alone', () => {
251
+ renderFrame({ height: 280 });
252
+ const style = contentBoxStyle();
253
+ expect(style.minHeight).toBe('auto');
254
+ expect(style.height).toBe('280px');
255
+ });
256
+ });
214
257
  });
@@ -1,7 +1,7 @@
1
1
  // @vitest-environment jsdom
2
2
  import React from 'react';
3
3
  import { afterEach, describe, expect, it, vi } from 'vitest';
4
- import { cleanup, render } from '@testing-library/react';
4
+ import { cleanup, render, screen } from '@testing-library/react';
5
5
  import { ThemeProvider, createTheme } from '@mui/material/styles';
6
6
 
7
7
  const chartSpy = vi.hoisted(() => vi.fn(() => <div data-testid="mui-line-chart" />));
@@ -33,4 +33,49 @@ describe('LineChart preset', () => {
33
33
  legend: { position: { vertical: 'bottom', horizontal: 'start' } },
34
34
  });
35
35
  });
36
+
37
+ // CHART-8: minHeight/height/aspect resolution, wired through the actual component.
38
+ describe('minHeight/height resolution (CHART-8)', () => {
39
+ function renderLine(props) {
40
+ return render(
41
+ <ThemeProvider theme={createTheme()}>
42
+ <LineChart series={[{ data: [1, 2] }]} {...props} />
43
+ </ThemeProvider>,
44
+ );
45
+ }
46
+
47
+ afterEach(cleanup);
48
+
49
+ it('sizes the chart from minHeight alone when neither height nor aspect is set', () => {
50
+ renderLine({ minHeight: 300 });
51
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(300);
52
+ expect(window.getComputedStyle(screen.getByTestId('line-chart-container')).minHeight).toBe('300px');
53
+ });
54
+
55
+ it('leaves minHeight as a floor and gives the chart no fixed height when aspect is set (no height)', () => {
56
+ renderLine({ minHeight: 320, aspect: 1.8 });
57
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBeUndefined();
58
+ const style = window.getComputedStyle(screen.getByTestId('line-chart-container'));
59
+ expect(style.minHeight).toBe('320px');
60
+ expect(style.aspectRatio).toBe('1.8 / 1');
61
+ });
62
+
63
+ it('caps the wrapper at height when minHeight is larger, closing the dead-space gap', () => {
64
+ renderLine({ minHeight: 420, height: 380 });
65
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(380);
66
+ expect(window.getComputedStyle(screen.getByTestId('line-chart-container')).minHeight).toBe('380px');
67
+ });
68
+
69
+ it('is byte-identical when minHeight equals height', () => {
70
+ renderLine({ minHeight: 320, height: 320 });
71
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(320);
72
+ expect(window.getComputedStyle(screen.getByTestId('line-chart-container')).minHeight).toBe('320px');
73
+ });
74
+
75
+ it('is unchanged when height is passed alone', () => {
76
+ renderLine({ height: 280 });
77
+ expect(chartSpy.mock.calls.at(-1)[0].height).toBe(280);
78
+ expect(window.getComputedStyle(screen.getByTestId('line-chart-container')).minHeight).toBe('auto');
79
+ });
80
+ });
36
81
  });
@@ -2,7 +2,7 @@
2
2
  import React from 'react';
3
3
  import i18next from 'i18next';
4
4
  import { afterEach, describe, expect, it, vi } from 'vitest';
5
- import { cleanup, render } from '@testing-library/react';
5
+ import { cleanup, render, screen } from '@testing-library/react';
6
6
  import { I18nextProvider } from 'react-i18next';
7
7
  import { ThemeProvider } from '@mui/material/styles';
8
8
 
@@ -232,3 +232,40 @@ describe('ScatterReferenceCurve / ScatterReferenceLine (THEME-10)', () => {
232
232
  expect(container.querySelector('text')).toBeNull();
233
233
  });
234
234
  });
235
+
236
+ // CHART-8: minHeight/height/aspect resolution, wired through the actual component.
237
+ describe('ScatterChart minHeight/height resolution (CHART-8)', () => {
238
+ afterEach(() => { cleanup(); vi.clearAllMocks(); });
239
+
240
+ it('sizes the chart from minHeight alone when neither height nor aspect is set', () => {
241
+ renderScatter({ minHeight: 300 });
242
+ expect(scatterSpy.mock.calls.at(-1)[0].height).toBe(300);
243
+ expect(window.getComputedStyle(screen.getByTestId('scatter-chart-container')).minHeight).toBe('300px');
244
+ });
245
+
246
+ it('leaves minHeight as a floor and gives the chart no fixed height when aspect is set (no height)', () => {
247
+ renderScatter({ minHeight: 320, aspect: 1.8 });
248
+ expect(scatterSpy.mock.calls.at(-1)[0].height).toBeUndefined();
249
+ const style = window.getComputedStyle(screen.getByTestId('scatter-chart-container'));
250
+ expect(style.minHeight).toBe('320px');
251
+ expect(style.aspectRatio).toBe('1.8 / 1');
252
+ });
253
+
254
+ it('caps the wrapper at height when minHeight is larger, closing the dead-space gap', () => {
255
+ renderScatter({ minHeight: 420, height: 380 });
256
+ expect(scatterSpy.mock.calls.at(-1)[0].height).toBe(380);
257
+ expect(window.getComputedStyle(screen.getByTestId('scatter-chart-container')).minHeight).toBe('380px');
258
+ });
259
+
260
+ it('is byte-identical when minHeight equals height', () => {
261
+ renderScatter({ minHeight: 320, height: 320 });
262
+ expect(scatterSpy.mock.calls.at(-1)[0].height).toBe(320);
263
+ expect(window.getComputedStyle(screen.getByTestId('scatter-chart-container')).minHeight).toBe('320px');
264
+ });
265
+
266
+ it('is unchanged when height is passed alone', () => {
267
+ renderScatter({ height: 280 });
268
+ expect(scatterSpy.mock.calls.at(-1)[0].height).toBe(280);
269
+ expect(window.getComputedStyle(screen.getByTestId('scatter-chart-container')).minHeight).toBe('auto');
270
+ });
271
+ });
@@ -17,7 +17,9 @@ import { TimeSeriesChart } from '../src/components/charts/TimeSeriesChart';
17
17
  import {
18
18
  defaultNumericTickFormatter,
19
19
  PACKAGE_DEFAULT_MARGIN,
20
+ resolveChartHeight,
20
21
  sizeYAxisForContent,
22
+ warnOnHeightMismatch,
21
23
  withAxisDefaults,
22
24
  withMarginDefaults,
23
25
  } from '../src/components/charts/chartDefaults';
@@ -433,3 +435,74 @@ describe('withMarginDefaults (THEME-11)', () => {
433
435
  expect(withMarginDefaults(full)).toEqual(full);
434
436
  });
435
437
  });
438
+
439
+ // CHART-8 -- pure-function contract of the minHeight/height/aspect resolver, independent of any
440
+ // chart component wiring (component-level wiring is covered per-preset in each own test file).
441
+ describe('resolveChartHeight (CHART-8)', () => {
442
+ it('sizes the chart from minHeight alone when neither height nor aspect is set', () => {
443
+ expect(resolveChartHeight({ minHeight: 300 })).toEqual({ wrapperMinHeight: 300, chartHeight: 300 });
444
+ });
445
+
446
+ it('leaves minHeight as a floor and gives the chart no fixed height when aspect is set (no height)', () => {
447
+ expect(resolveChartHeight({ minHeight: 320, aspect: 1.8 })).toEqual({
448
+ wrapperMinHeight: 320,
449
+ chartHeight: undefined,
450
+ });
451
+ });
452
+
453
+ it('caps the wrapper at height when minHeight is larger, closing the dead-space gap', () => {
454
+ expect(resolveChartHeight({ minHeight: 420, height: 380 })).toEqual({
455
+ wrapperMinHeight: 380,
456
+ chartHeight: 380,
457
+ });
458
+ });
459
+
460
+ it('is byte-identical (both values unchanged) when minHeight equals height', () => {
461
+ expect(resolveChartHeight({ minHeight: 320, height: 320 })).toEqual({
462
+ wrapperMinHeight: 320,
463
+ chartHeight: 320,
464
+ });
465
+ });
466
+
467
+ it('leaves the wrapper unset when height is passed alone', () => {
468
+ expect(resolveChartHeight({ height: 280 })).toEqual({ wrapperMinHeight: undefined, chartHeight: 280 });
469
+ });
470
+
471
+ it('does not cap the wrapper when minHeight is smaller than height', () => {
472
+ expect(resolveChartHeight({ minHeight: 200, height: 380 })).toEqual({
473
+ wrapperMinHeight: 200,
474
+ chartHeight: 380,
475
+ });
476
+ });
477
+ });
478
+
479
+ describe('warnOnHeightMismatch (CHART-8)', () => {
480
+ afterEach(() => vi.restoreAllMocks());
481
+
482
+ it('warns, naming the component and both values, when minHeight and height disagree', () => {
483
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
484
+ warnOnHeightMismatch('BarChart', { minHeight: 420, height: 380 });
485
+ expect(warn).toHaveBeenCalledOnce();
486
+ expect(warn.mock.calls[0][0]).toContain('BarChart');
487
+ expect(warn.mock.calls[0][0]).toContain('420');
488
+ expect(warn.mock.calls[0][0]).toContain('380');
489
+ });
490
+
491
+ it('does not warn when minHeight equals height', () => {
492
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
493
+ warnOnHeightMismatch('BarChart', { minHeight: 320, height: 320 });
494
+ expect(warn).not.toHaveBeenCalled();
495
+ });
496
+
497
+ it('does not warn on the legitimate minHeight + aspect (no height) combination', () => {
498
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
499
+ warnOnHeightMismatch('BarChart', { minHeight: 320, height: undefined });
500
+ expect(warn).not.toHaveBeenCalled();
501
+ });
502
+
503
+ it('does not warn when only one of the pair is set', () => {
504
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {});
505
+ warnOnHeightMismatch('BarChart', { minHeight: undefined, height: 280 });
506
+ expect(warn).not.toHaveBeenCalled();
507
+ });
508
+ });
@@ -24,10 +24,7 @@ import {
24
24
  } from '../src/index';
25
25
 
26
26
  const I18N_DIRECTORY = path.resolve('src/i18n');
27
- // Scoped to the three locales every bundle already carries. `messagingTranslations`'s 116 keys
28
- // have no `sw` value yet (pre-existing gap, out of I18N-1's scope — see the Notiz on the
29
- // I18N-1 register row for the tracked follow-up to backfill it and restore `sw` here).
30
- const REQUIRED_LOCALES = ['de', 'en', 'fr'];
27
+ const REQUIRED_LOCALES = ['de', 'en', 'fr', 'sw'];
31
28
  const bundleImporters = import.meta.glob('../src/i18n/*.ts');
32
29
  const PUBLIC_BUNDLES = {
33
30
  authTranslations: publicAuthTranslations,
@@ -99,7 +99,7 @@ describe('MSG-6 messaging regressions', () => {
99
99
  await waitFor(() => expect(screen.queryByLabelText(/MessagingThread.UNREAD_REPLIES/)).toBeNull());
100
100
  });
101
101
 
102
- it('defines singular reply labels for de, en, and fr', () => {
103
- expect(messagingTranslations['MessagingThread.SHOW_REPLIES_one']).toEqual({ de: '{{count}} Antwort anzeigen', en: 'Show {{count}} reply', fr: 'Afficher {{count}} réponse' });
102
+ it('defines singular reply labels for de, en, fr, and sw', () => {
103
+ expect(messagingTranslations['MessagingThread.SHOW_REPLIES_one']).toEqual({ de: '{{count}} Antwort anzeigen', en: 'Show {{count}} reply', fr: 'Afficher {{count}} réponse', sw: 'Onyesha jibu {{count}}' });
104
104
  });
105
105
  });