From 02f078ca50e80f59ca5d46f5fdf8ff5e98479d4d Mon Sep 17 00:00:00 2001 From: Jean-Marie Favreau Date: Fri, 14 Mar 2025 12:39:56 +0100 Subject: [PATCH] =?UTF-8?q?On=20ajoute=20la=20possibilite=20d'ajouter=20de?= =?UTF-8?q?s=20messages=20sur=20les=20=C3=A9v=C3=A9nements=20suivant=20les?= =?UTF-8?q?=20=C3=A9tiquettes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agenda_culturel/forms.py | 1 + .../locale/fr/LC_MESSAGES/django.po | 551 +++++++++--------- .../migrations/0154_tag_message.py | 24 + src/agenda_culturel/models.py | 18 + src/agenda_culturel/static/style.scss | 4 + .../single-event/event-single-inc.html | 1 + 6 files changed, 327 insertions(+), 272 deletions(-) create mode 100644 src/agenda_culturel/migrations/0154_tag_message.py diff --git a/src/agenda_culturel/forms.py b/src/agenda_culturel/forms.py index 2d85989..9cea6e9 100644 --- a/src/agenda_culturel/forms.py +++ b/src/agenda_culturel/forms.py @@ -123,6 +123,7 @@ class TagForm(ModelForm): fields = [ "name", "description", + "message", "in_included_suggestions", "in_excluded_suggestions", "principal", diff --git a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po index 64505af..478bd37 100644 --- a/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po +++ b/src/agenda_culturel/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: agenda_culturel\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-03-13 22:05+0100\n" +"POT-Creation-Date: 2025-03-14 12:29+0100\n" "PO-Revision-Date: 2023-10-29 14:16+0000\n" "Last-Translator: Jean-Marie Favreau \n" "Language-Team: Jean-Marie Favreau \n" @@ -90,87 +90,89 @@ msgstr "Après-midi" msgid "Evening" msgstr "Soir" -#: agenda_culturel/filters.py:34 +#: agenda_culturel/filters.py:35 msgid "Select a location" msgstr "Choisir une localité" -#: agenda_culturel/filters.py:343 -msgid "Representative version" -msgstr "Version représentative" - -#: agenda_culturel/filters.py:344 agenda_culturel/filters.py:351 -#: agenda_culturel/filters.py:358 agenda_culturel/filters.py:486 -msgid "Yes" -msgstr "Oui" - -#: agenda_culturel/filters.py:344 agenda_culturel/filters.py:351 -#: agenda_culturel/filters.py:358 agenda_culturel/filters.py:486 +#: agenda_culturel/filters.py:52 agenda_culturel/filters.py:371 +#: agenda_culturel/filters.py:378 agenda_culturel/filters.py:385 +#: agenda_culturel/filters.py:513 msgid "No" msgstr "Non" -#: agenda_culturel/filters.py:350 +#: agenda_culturel/filters.py:52 agenda_culturel/filters.py:371 +#: agenda_culturel/filters.py:378 agenda_culturel/filters.py:385 +#: agenda_culturel/filters.py:513 +msgid "Yes" +msgstr "Oui" + +#: agenda_culturel/filters.py:370 +msgid "Representative version" +msgstr "Version représentative" + +#: agenda_culturel/filters.py:377 msgid "Pure import" msgstr "Événement importé" -#: agenda_culturel/filters.py:357 +#: agenda_culturel/filters.py:384 msgid "In recurrent import" msgstr "Inclut dans un import récurrent" -#: agenda_culturel/filters.py:364 +#: agenda_culturel/filters.py:391 msgid "Sort by" msgstr "Trier par" -#: agenda_culturel/filters.py:366 +#: agenda_culturel/filters.py:393 msgid "last moderated first" msgstr "dernier modéré d'abord" -#: agenda_culturel/filters.py:367 +#: agenda_culturel/filters.py:394 msgid "last modified first" msgstr "dernier modifié d'abord" -#: agenda_culturel/filters.py:368 +#: agenda_culturel/filters.py:395 msgid "last imported first" msgstr "dernier importé d'abord" -#: agenda_culturel/filters.py:369 +#: agenda_culturel/filters.py:396 msgid "last created first" msgstr "dernier créé d'abord" -#: agenda_culturel/filters.py:375 +#: agenda_culturel/filters.py:402 msgid "Imported from" msgstr "Importé depuis" -#: agenda_culturel/filters.py:443 agenda_culturel/models.py:718 -#: agenda_culturel/models.py:2675 +#: agenda_culturel/filters.py:470 agenda_culturel/models.py:725 +#: agenda_culturel/models.py:2687 msgid "Status" msgstr "Status" -#: agenda_culturel/filters.py:444 agenda_culturel/models.py:2441 +#: agenda_culturel/filters.py:471 agenda_culturel/models.py:2453 msgid "Closed" msgstr "Fermé" -#: agenda_culturel/filters.py:444 +#: agenda_culturel/filters.py:471 msgid "Open" msgstr "Ouvert" -#: agenda_culturel/filters.py:448 agenda_culturel/filters.py:449 -#: agenda_culturel/models.py:2435 +#: agenda_culturel/filters.py:475 agenda_culturel/filters.py:476 +#: agenda_culturel/models.py:2447 msgid "Spam" msgstr "Spam" -#: agenda_culturel/filters.py:449 +#: agenda_culturel/filters.py:476 msgid "Non spam" msgstr "Non spam" -#: agenda_culturel/filters.py:454 agenda_culturel/models.py:2456 +#: agenda_culturel/filters.py:481 agenda_culturel/models.py:2468 msgid "Type" msgstr "Type" -#: agenda_culturel/filters.py:473 +#: agenda_culturel/filters.py:500 msgid "Search" msgstr "Rechercher" -#: agenda_culturel/filters.py:485 +#: agenda_culturel/filters.py:512 msgid "In the past" msgstr "Dans le passé" @@ -178,111 +180,111 @@ msgstr "Dans le passé" msgid "Other" msgstr "Autres" -#: agenda_culturel/forms.py:140 +#: agenda_culturel/forms.py:141 msgid "Name of new tag" msgstr "Nom de la nouvelle étiquette" -#: agenda_culturel/forms.py:144 +#: agenda_culturel/forms.py:145 msgid "" "Force renaming despite the existence of events already using the chosen tag." msgstr "" "Forcer le renommage malgré l'existence d'événements utilisant déjà " "l'étiquette choisie." -#: agenda_culturel/forms.py:163 +#: agenda_culturel/forms.py:164 msgid "Your email" msgstr "Votre adresse email" -#: agenda_culturel/forms.py:164 agenda_culturel/models.py:2423 +#: agenda_culturel/forms.py:165 agenda_culturel/models.py:2435 msgid "Your email address" msgstr "Votre adresse email" -#: agenda_culturel/forms.py:170 agenda_culturel/models.py:2448 +#: agenda_culturel/forms.py:171 agenda_culturel/models.py:2460 msgid "Comments" msgstr "Commentaires" -#: agenda_culturel/forms.py:172 +#: agenda_culturel/forms.py:173 msgid "" "Your message for the moderation team (comments, clarifications, requests...)" msgstr "" "Votre message pour l'équipe de modération (commentaires, précisions, " "demandes, ...)" -#: agenda_culturel/forms.py:187 +#: agenda_culturel/forms.py:188 msgid "Receive notification of publication or leave a message for moderation" msgstr "Être notifié de la publication ou laisser un message à la modération" -#: agenda_culturel/forms.py:204 agenda_culturel/models.py:179 -#: agenda_culturel/models.py:726 agenda_culturel/models.py:2599 -#: agenda_culturel/models.py:2710 +#: agenda_culturel/forms.py:205 agenda_culturel/models.py:179 +#: agenda_culturel/models.py:733 agenda_culturel/models.py:2611 +#: agenda_culturel/models.py:2722 msgid "Category" msgstr "Catégorie" -#: agenda_culturel/forms.py:210 agenda_culturel/forms.py:243 -#: agenda_culturel/forms.py:271 agenda_culturel/forms.py:442 -#: agenda_culturel/models.py:223 agenda_culturel/models.py:843 +#: agenda_culturel/forms.py:211 agenda_culturel/forms.py:244 +#: agenda_culturel/forms.py:272 agenda_culturel/forms.py:443 +#: agenda_culturel/models.py:230 agenda_culturel/models.py:850 msgid "Tags" msgstr "Étiquettes" -#: agenda_culturel/forms.py:218 agenda_culturel/forms.py:595 -#: agenda_culturel/models.py:944 +#: agenda_culturel/forms.py:219 agenda_culturel/forms.py:603 +#: agenda_culturel/models.py:951 msgid "Event" msgstr "Événement" -#: agenda_culturel/forms.py:325 +#: agenda_culturel/forms.py:326 msgid "Main fields" msgstr "Champs principaux" -#: agenda_culturel/forms.py:328 +#: agenda_culturel/forms.py:329 msgid "Start of event" msgstr "Début de l'événement" -#: agenda_culturel/forms.py:332 +#: agenda_culturel/forms.py:333 msgid "End of event" msgstr "Fin de l'événement" -#: agenda_culturel/forms.py:338 +#: agenda_culturel/forms.py:339 msgid "This is a recurring event" msgstr "Cet événement est récurrent" -#: agenda_culturel/forms.py:350 +#: agenda_culturel/forms.py:351 msgid "Details" msgstr "Détails" -#: agenda_culturel/forms.py:355 agenda_culturel/models.py:755 -#: agenda_culturel/models.py:2574 +#: agenda_culturel/forms.py:356 agenda_culturel/models.py:762 +#: agenda_culturel/models.py:2586 msgid "Location" msgstr "Localisation" -#: agenda_culturel/forms.py:360 agenda_culturel/models.py:799 +#: agenda_culturel/forms.py:361 agenda_culturel/models.py:806 msgid "Illustration" msgstr "Illustration" -#: agenda_culturel/forms.py:364 +#: agenda_culturel/forms.py:365 msgid "URLs" msgstr "URLs" -#: agenda_culturel/forms.py:368 agenda_culturel/forms.py:373 +#: agenda_culturel/forms.py:369 agenda_culturel/forms.py:374 msgid "Meta information" msgstr "Méta-informations" -#: agenda_culturel/forms.py:388 +#: agenda_culturel/forms.py:389 msgid "The end date must be after the start date." msgstr "La date de fin doit être après la date de début." -#: agenda_culturel/forms.py:404 +#: agenda_culturel/forms.py:405 msgid "The end time cannot be earlier than the start time." msgstr "L'heure de fin ne peut pas être avant l'heure de début." -#: agenda_culturel/forms.py:443 +#: agenda_culturel/forms.py:444 msgid "Select tags from existing ones." msgstr "Sélectionner des étiquettes depuis celles existantes." -#: agenda_culturel/forms.py:448 +#: agenda_culturel/forms.py:449 msgid "New tags" msgstr "Nouvelles étiquettes" -#: agenda_culturel/forms.py:450 +#: agenda_culturel/forms.py:451 msgid "" "Create new labels (sparingly). Note: by starting your tag with the " "characters “TW:”, youll create a “trigger warning” tag, and the associated " @@ -293,92 +295,92 @@ msgstr "" "étiquette “trigger warning”, et les événements associés seront annoncés " "comme tels." -#: agenda_culturel/forms.py:492 +#: agenda_culturel/forms.py:500 msgid "JSON in the format expected for the import." msgstr "JSON dans le format attendu pour l'import" -#: agenda_culturel/forms.py:514 +#: agenda_culturel/forms.py:522 msgid " (locally modified version)" msgstr " (version modifiée localement)" -#: agenda_culturel/forms.py:518 +#: agenda_culturel/forms.py:526 msgid " (synchronized on import version)" msgstr " (version synchronisée sur l'import)" -#: agenda_culturel/forms.py:522 +#: agenda_culturel/forms.py:530 msgid "Select {} as representative version." msgstr "Sélectionner {} comme version représentative" -#: agenda_culturel/forms.py:532 +#: agenda_culturel/forms.py:540 msgid "Update {} using some fields from other versions (interactive mode)." msgstr "" "Mettre à jour {} en utilisant quelques champs des autres versions (mode " "interactif)." -#: agenda_culturel/forms.py:539 +#: agenda_culturel/forms.py:547 msgid " Warning: a version is already locally modified." msgstr " Attention: une version a déjà été modifiée localement." -#: agenda_culturel/forms.py:546 +#: agenda_culturel/forms.py:554 msgid "Create a new version by merging (interactive mode)." msgstr "Créer une nouvelle version par fusion (mode interactif)." -#: agenda_culturel/forms.py:554 +#: agenda_culturel/forms.py:562 msgid "Make {} independent." msgstr "Rendre {} indépendant." -#: agenda_culturel/forms.py:557 +#: agenda_culturel/forms.py:565 msgid "Make all versions independent." msgstr "Rendre toutes les versions indépendantes." -#: agenda_culturel/forms.py:629 agenda_culturel/forms.py:642 +#: agenda_culturel/forms.py:637 agenda_culturel/forms.py:650 msgid "Value of version {}" msgstr "Valeur de la version {}" -#: agenda_culturel/forms.py:634 +#: agenda_culturel/forms.py:642 msgid "Value of the selected version" msgstr "Valeur de la version sélectionnée" -#: agenda_culturel/forms.py:804 +#: agenda_culturel/forms.py:812 msgid "Apply category {} to the event {}" msgstr "Appliquer la catégorie {} à l'événement {}" -#: agenda_culturel/forms.py:821 agenda_culturel/models.py:554 -#: agenda_culturel/models.py:2762 +#: agenda_culturel/forms.py:829 agenda_culturel/models.py:561 +#: agenda_culturel/models.py:2774 msgid "Place" msgstr "Lieu" -#: agenda_culturel/forms.py:823 +#: agenda_culturel/forms.py:831 msgid "Create a missing place" msgstr "Créer un lieu manquant" -#: agenda_culturel/forms.py:833 +#: agenda_culturel/forms.py:841 msgid "Add \"{}\" to the aliases of the place" msgstr "Ajouter « {} » aux alias du lieu" -#: agenda_culturel/forms.py:862 +#: agenda_culturel/forms.py:870 msgid "On saving, use aliases to detect all matching events with missing place" msgstr "" "Lors de l'enregistrement, utiliser des alias pour détecter tous les " "événements correspondants dont la place est manquante." -#: agenda_culturel/forms.py:875 +#: agenda_culturel/forms.py:883 msgid "Header" msgstr "Entête" -#: agenda_culturel/forms.py:878 agenda_culturel/models.py:516 +#: agenda_culturel/forms.py:886 agenda_culturel/models.py:523 msgid "Address" msgstr "Adresse" -#: agenda_culturel/forms.py:884 +#: agenda_culturel/forms.py:892 msgid "Meta" msgstr "Méta" -#: agenda_culturel/forms.py:887 +#: agenda_culturel/forms.py:895 msgid "Information" msgstr "Informations" -#: agenda_culturel/forms.py:939 +#: agenda_culturel/forms.py:947 msgid "Add a comment" msgstr "Ajouter un commentaire" @@ -412,9 +414,9 @@ msgstr "" "sans doute été trop court" #: agenda_culturel/models.py:62 agenda_culturel/models.py:109 -#: agenda_culturel/models.py:188 agenda_culturel/models.py:473 -#: agenda_culturel/models.py:514 agenda_culturel/models.py:620 -#: agenda_culturel/models.py:2415 agenda_culturel/models.py:2524 +#: agenda_culturel/models.py:188 agenda_culturel/models.py:480 +#: agenda_culturel/models.py:521 agenda_culturel/models.py:627 +#: agenda_culturel/models.py:2427 agenda_culturel/models.py:2536 msgid "Name" msgstr "Nom" @@ -474,8 +476,8 @@ msgstr "Catégories" msgid "Tag name" msgstr "Nom de l'étiquette" -#: agenda_culturel/models.py:195 agenda_culturel/models.py:537 -#: agenda_culturel/models.py:636 agenda_culturel/models.py:782 +#: agenda_culturel/models.py:195 agenda_culturel/models.py:544 +#: agenda_culturel/models.py:643 agenda_culturel/models.py:789 msgid "Description" msgstr "Description" @@ -483,11 +485,20 @@ msgstr "Description" msgid "Description of the tag" msgstr "Description de l'étiquette" -#: agenda_culturel/models.py:202 +#: agenda_culturel/models.py:202 agenda_culturel/models.py:2394 +#: agenda_culturel/models.py:2441 +msgid "Message" +msgstr "Message" + +#: agenda_culturel/models.py:203 +msgid "Message displayed to the user on each event associated with this tag." +msgstr "Message affiché à l'utilisateur sur chaque événement associé à cette étiquette." + +#: agenda_culturel/models.py:209 msgid "Principal" msgstr "Principal" -#: agenda_culturel/models.py:204 +#: agenda_culturel/models.py:211 msgid "" "This tag is highlighted as a main tag for visitors, particularly in the " "filter." @@ -495,91 +506,91 @@ msgstr "" "Cette étiquette est mise en avant comme étiquette principale pour les " "visiteurs, en particulier dans le filtre." -#: agenda_culturel/models.py:210 +#: agenda_culturel/models.py:217 msgid "In excluded suggestions" msgstr "Dans les suggestions d'exclusion" -#: agenda_culturel/models.py:211 +#: agenda_culturel/models.py:218 msgid "This tag will be part of the excluded suggestions." msgstr "Cette étiquette fera partie des suggestions d'exclusion." -#: agenda_culturel/models.py:216 +#: agenda_culturel/models.py:223 msgid "In included suggestions" msgstr "Dans les suggestions d'inclusion." -#: agenda_culturel/models.py:217 +#: agenda_culturel/models.py:224 msgid "This tag will be part of the included suggestions." msgstr "Cette étiquette fera partie des suggestions d'inclusion." -#: agenda_culturel/models.py:222 +#: agenda_culturel/models.py:229 msgid "Tag" msgstr "Étiquette" -#: agenda_culturel/models.py:311 +#: agenda_culturel/models.py:318 msgid "Suggestions" msgstr "Suggestions" -#: agenda_culturel/models.py:312 +#: agenda_culturel/models.py:319 msgid "Others" msgstr "Autres" -#: agenda_culturel/models.py:325 +#: agenda_culturel/models.py:332 msgid "Representative event" msgstr "Événement représentatif" -#: agenda_culturel/models.py:327 +#: agenda_culturel/models.py:334 msgid "This event is the representative event of the duplicated events group" msgstr "" "Cet événement est l'événement représentatif du groupe d'événements dupliqués." -#: agenda_culturel/models.py:335 agenda_culturel/models.py:336 +#: agenda_culturel/models.py:342 agenda_culturel/models.py:343 msgid "Duplicated events" msgstr "Événements dupliqués" -#: agenda_culturel/models.py:474 +#: agenda_culturel/models.py:481 msgid "Name of the location" msgstr "Nom de la position" -#: agenda_culturel/models.py:485 +#: agenda_culturel/models.py:492 msgid "Main" msgstr "Principale" -#: agenda_culturel/models.py:487 +#: agenda_culturel/models.py:494 msgid "This location is one of the main locations (shown first higher values)." msgstr "" "Cette position est une position principale (affichage en premier des plus " "grandes valeurs)." -#: agenda_culturel/models.py:492 +#: agenda_culturel/models.py:499 msgid "Suggested distance (km)" msgstr "" -#: agenda_culturel/models.py:494 +#: agenda_culturel/models.py:501 msgid "" "If this distance is given, this location is part of the suggested filters." msgstr "" -#: agenda_culturel/models.py:503 +#: agenda_culturel/models.py:510 msgid "Reference location" msgstr "Position de référence" -#: agenda_culturel/models.py:504 +#: agenda_culturel/models.py:511 msgid "Reference locations" msgstr "Positions de référence" -#: agenda_culturel/models.py:514 +#: agenda_culturel/models.py:521 msgid "Name of the place" msgstr "Nom du lieu" -#: agenda_culturel/models.py:517 +#: agenda_culturel/models.py:524 msgid "Address of this place (without city name)" msgstr "Adresse de ce lieu (sans le nom de la ville)" -#: agenda_culturel/models.py:522 +#: agenda_culturel/models.py:529 msgid "Postcode" msgstr "Code postal" -#: agenda_culturel/models.py:524 +#: agenda_culturel/models.py:531 msgid "" "The post code is not displayed, but makes it easier to find an address when " "you enter it." @@ -587,23 +598,23 @@ msgstr "" "Le code postal ne sera pas affiché, mais facilite la recherche d'adresse au " "moment de la saisie." -#: agenda_culturel/models.py:529 +#: agenda_culturel/models.py:536 msgid "City" msgstr "Ville" -#: agenda_culturel/models.py:529 +#: agenda_culturel/models.py:536 msgid "City name" msgstr "Nom de la ville" -#: agenda_culturel/models.py:538 +#: agenda_culturel/models.py:545 msgid "Description of the place, including accessibility." msgstr "Description du lieu, inclus l'accessibilité." -#: agenda_culturel/models.py:545 +#: agenda_culturel/models.py:552 msgid "Alternative names" msgstr "Noms alternatifs" -#: agenda_culturel/models.py:547 +#: agenda_culturel/models.py:554 msgid "" "Alternative names or addresses used to match a place with the free-form " "location of an event." @@ -611,31 +622,31 @@ msgstr "" "Noms et adresses alternatives qui seront utilisées pour associer une adresse " "avec la localisation en forme libre d'un événement" -#: agenda_culturel/models.py:555 +#: agenda_culturel/models.py:562 msgid "Places" msgstr "Lieux" -#: agenda_culturel/models.py:621 +#: agenda_culturel/models.py:628 msgid "Organisation name" msgstr "Nom de l'organisme" -#: agenda_culturel/models.py:628 +#: agenda_culturel/models.py:635 msgid "Website" msgstr "Site internet" -#: agenda_culturel/models.py:629 +#: agenda_culturel/models.py:636 msgid "Website of the organisation" msgstr "Site internet de l'organisme" -#: agenda_culturel/models.py:637 +#: agenda_culturel/models.py:644 msgid "Description of the organisation." msgstr "Description de l'organisme" -#: agenda_culturel/models.py:644 +#: agenda_culturel/models.py:651 msgid "Principal place" msgstr "Lieu principal" -#: agenda_culturel/models.py:646 +#: agenda_culturel/models.py:653 msgid "" "Place mainly associated with this organizer. Mainly used if there is a " "similarity in the name, to avoid redundant displays." @@ -643,71 +654,71 @@ msgstr "" "Lieu principalement associé à cet organisateur. Principalement utilisé s'il " "y a une similarité de nom, pour éviter les affichages redondants." -#: agenda_culturel/models.py:654 +#: agenda_culturel/models.py:661 msgid "Organisation" msgstr "Organisme" -#: agenda_culturel/models.py:655 +#: agenda_culturel/models.py:662 msgid "Organisations" msgstr "Organismes" -#: agenda_culturel/models.py:666 agenda_culturel/models.py:2569 +#: agenda_culturel/models.py:673 agenda_culturel/models.py:2581 msgid "Published" msgstr "Publié" -#: agenda_culturel/models.py:667 +#: agenda_culturel/models.py:674 msgid "Draft" msgstr "Brouillon" -#: agenda_culturel/models.py:668 +#: agenda_culturel/models.py:675 msgid "Trash" msgstr "Corbeille" -#: agenda_culturel/models.py:677 +#: agenda_culturel/models.py:684 msgid "Author of the event creation" msgstr "Auteur de la création de l'événement" -#: agenda_culturel/models.py:686 +#: agenda_culturel/models.py:693 msgid "Author of the last importation" msgstr "Auteur de la dernière importation" -#: agenda_culturel/models.py:695 +#: agenda_culturel/models.py:702 msgid "Author of the last modification" msgstr "Auteur de la dernière modification" -#: agenda_culturel/models.py:704 +#: agenda_culturel/models.py:711 msgid "Author of the last moderation" msgstr "Auteur de la dernière modération" -#: agenda_culturel/models.py:715 +#: agenda_culturel/models.py:722 msgid "Title" msgstr "Titre" -#: agenda_culturel/models.py:732 +#: agenda_culturel/models.py:739 msgid "Start day" msgstr "Date de début" -#: agenda_culturel/models.py:734 +#: agenda_culturel/models.py:741 msgid "Start time" msgstr "Heure de début" -#: agenda_culturel/models.py:740 +#: agenda_culturel/models.py:747 msgid "End day" msgstr "Date de fin" -#: agenda_culturel/models.py:744 +#: agenda_culturel/models.py:751 msgid "End time" msgstr "Heure de fin" -#: agenda_culturel/models.py:747 +#: agenda_culturel/models.py:754 msgid "Recurrence" msgstr "Récurrence" -#: agenda_culturel/models.py:761 +#: agenda_culturel/models.py:768 msgid "Location (free form)" msgstr "Localisation (forme libre)" -#: agenda_culturel/models.py:763 +#: agenda_culturel/models.py:770 msgid "" "Address of the event in case its not available in the already known places " "(free form)" @@ -715,25 +726,25 @@ msgstr "" "Adresse d'un événement si elle n'est pas déjà présente dans la liste des " "lieux disponibles (forme libre)" -#: agenda_culturel/models.py:772 +#: agenda_culturel/models.py:779 msgid "Local event" msgstr "Événement de portée locale" -#: agenda_culturel/models.py:774 +#: agenda_culturel/models.py:781 msgid "" "If the event is a local event, it will not be proposed by default in daily, " "weekly or monthly views, unless the user has explicitly indicated that he " "wishes to see these events." msgstr "" "Si l'événement est de portée locale, il ne sera pas proposé par défaut dans " -"les vues quotidiennes, hebdomadaires ou mensuelles, sauf si l'utilisateur " -"a explicitement indiqué qu'il souhaite voir ces événements." +"les vues quotidiennes, hebdomadaires ou mensuelles, sauf si l'utilisateur a " +"explicitement indiqué qu'il souhaite voir ces événements." -#: agenda_culturel/models.py:790 +#: agenda_culturel/models.py:797 msgid "Organisers" msgstr "Organisateurs" -#: agenda_culturel/models.py:792 +#: agenda_culturel/models.py:799 msgid "" "list of event organisers. Organizers will only be displayed if one of them " "does not normally use the venue." @@ -741,112 +752,112 @@ msgstr "" "Liste des organisateurs de l'événements. Les organisateurs seront affichés " "uniquement si au moins un d'entre eux n'utilise pas habituellement le lieu." -#: agenda_culturel/models.py:806 +#: agenda_culturel/models.py:813 msgid "Illustration (URL)" msgstr "Illustration (URL)" -#: agenda_culturel/models.py:807 +#: agenda_culturel/models.py:814 msgid "External URL of the illustration image" msgstr "URL externe de l'image illustrative" -#: agenda_culturel/models.py:813 +#: agenda_culturel/models.py:820 msgid "Illustration description" msgstr "Description de l'illustration" -#: agenda_culturel/models.py:814 +#: agenda_culturel/models.py:821 msgid "Alternative text used by screen readers for the image" msgstr "Texte alternatif utiliser par les lecteurs d'écrans pour l'image" -#: agenda_culturel/models.py:822 +#: agenda_culturel/models.py:829 msgid "Importation source" msgstr "Source d'importation" -#: agenda_culturel/models.py:823 +#: agenda_culturel/models.py:830 msgid "Importation source used to detect removed entries." msgstr "Source d'importation utilisée pour détecter les éléments supprimés/" -#: agenda_culturel/models.py:829 +#: agenda_culturel/models.py:836 msgid "UUIDs" msgstr "UUIDs" -#: agenda_culturel/models.py:830 +#: agenda_culturel/models.py:837 msgid "UUIDs from import to detect duplicated entries." msgstr "UUIDs utilisés pendant l'import pour détecter les entrées dupliquées" -#: agenda_culturel/models.py:836 +#: agenda_culturel/models.py:843 msgid "Online sources or ticketing" msgstr "Sources en ligne ou billetterie" -#: agenda_culturel/models.py:850 +#: agenda_culturel/models.py:857 msgid "Other versions" msgstr "" -#: agenda_culturel/models.py:945 +#: agenda_culturel/models.py:952 msgid "Events" msgstr "Événements" -#: agenda_culturel/models.py:1001 +#: agenda_culturel/models.py:1008 msgid "recurrent import" msgstr "import récurrent" -#: agenda_culturel/models.py:1003 +#: agenda_culturel/models.py:1010 msgid "a non authenticated user" msgstr "un utilisateur non connecté" -#: agenda_culturel/models.py:1470 +#: agenda_culturel/models.py:1482 msgid "Your event has been published" msgstr "Ton événement a été publié" -#: agenda_culturel/models.py:1475 +#: agenda_culturel/models.py:1487 msgid "Your message has not been retained" msgstr "Ton événement n'a pas été retenu" -#: agenda_culturel/models.py:1563 agenda_culturel/models.py:2379 +#: agenda_culturel/models.py:1575 agenda_culturel/models.py:2391 msgid "Warning" msgstr "Warning" -#: agenda_culturel/models.py:1565 agenda_culturel/models.py:1671 +#: agenda_culturel/models.py:1577 agenda_culturel/models.py:1683 msgid "the date has not been imported correctly." msgstr "la date n'a pas été importée correctement." -#: agenda_culturel/models.py:1653 +#: agenda_culturel/models.py:1665 msgid "during import process" msgstr "pendant le processus d'import" -#: agenda_culturel/models.py:1669 agenda_culturel/models.py:1679 -#: agenda_culturel/models.py:1690 +#: agenda_culturel/models.py:1681 agenda_culturel/models.py:1691 +#: agenda_culturel/models.py:1702 msgid "warning" msgstr "attention" -#: agenda_culturel/models.py:1681 +#: agenda_culturel/models.py:1693 msgid "the title has not been imported correctly." msgstr "le titre n'a pas été importé correctement." -#: agenda_culturel/models.py:1693 +#: agenda_culturel/models.py:1705 msgid "The import was unable to find an event in the page." msgstr "L'import a été incapable de trouver un événement dans la page." -#: agenda_culturel/models.py:2041 +#: agenda_culturel/models.py:2053 msgid "Updated field(s): " msgstr "Champ(s) mis à jour: " -#: agenda_culturel/models.py:2045 +#: agenda_culturel/models.py:2057 msgid "Update" msgstr "Mise à jour" -#: agenda_culturel/models.py:2046 +#: agenda_culturel/models.py:2058 msgid "update process" msgstr "processus de mise à jour" -#: agenda_culturel/models.py:2115 +#: agenda_culturel/models.py:2127 msgid "Import" msgstr "Import" -#: agenda_culturel/models.py:2116 +#: agenda_culturel/models.py:2128 msgid "import process" msgstr "processus d'import" -#: agenda_culturel/models.py:2118 +#: agenda_culturel/models.py:2130 msgid "" "The duration of the event is a little too long for direct publication. " "Moderators can choose to publish it or not." @@ -854,191 +865,187 @@ msgstr "" "La durée de l'événement est un peu trop longue pour qu'il soit publié " "directement. Les modérateurs peuvent choisir de le publier ou non." -#: agenda_culturel/models.py:2370 +#: agenda_culturel/models.py:2382 msgid "From contributor" msgstr "D'un·e contributeurice" -#: agenda_culturel/models.py:2371 +#: agenda_culturel/models.py:2383 msgid "Import process" msgstr "Processus d'import" -#: agenda_culturel/models.py:2372 +#: agenda_culturel/models.py:2384 msgid "Update process" msgstr "Processus de mise à jour" -#: agenda_culturel/models.py:2373 +#: agenda_culturel/models.py:2385 msgid "Contact form" msgstr "Formulaire de contact" -#: agenda_culturel/models.py:2374 +#: agenda_culturel/models.py:2386 msgid "Event report" msgstr "Signalemet d'événement" -#: agenda_culturel/models.py:2377 +#: agenda_culturel/models.py:2389 msgid "From contributor (without message)" msgstr "D'un·e contributeurice (sans message)" -#: agenda_culturel/models.py:2382 agenda_culturel/models.py:2429 -msgid "Message" -msgstr "Message" - -#: agenda_culturel/models.py:2383 +#: agenda_culturel/models.py:2395 msgid "Messages" msgstr "Messages" -#: agenda_culturel/models.py:2392 +#: agenda_culturel/models.py:2404 msgid "Subject" msgstr "Sujet" -#: agenda_culturel/models.py:2393 +#: agenda_culturel/models.py:2405 msgid "The subject of your message" msgstr "Sujet de votre message" -#: agenda_culturel/models.py:2399 +#: agenda_culturel/models.py:2411 msgid "Related event" msgstr "Événement associé" -#: agenda_culturel/models.py:2400 +#: agenda_culturel/models.py:2412 msgid "The message is associated with this event." msgstr "Le message est associé à cet événement." -#: agenda_culturel/models.py:2408 +#: agenda_culturel/models.py:2420 msgid "Author of the message" msgstr "Auteur du message" -#: agenda_culturel/models.py:2416 +#: agenda_culturel/models.py:2428 msgid "Your name" msgstr "Votre nom" -#: agenda_culturel/models.py:2422 +#: agenda_culturel/models.py:2434 msgid "Email address" msgstr "Adresse email" -#: agenda_culturel/models.py:2429 +#: agenda_culturel/models.py:2441 msgid "Your message" msgstr "Votre message" -#: agenda_culturel/models.py:2436 +#: agenda_culturel/models.py:2448 msgid "This message is a spam." msgstr "Ce message est un spam." -#: agenda_culturel/models.py:2443 +#: agenda_culturel/models.py:2455 msgid "this message has been processed and no longer needs to be handled" msgstr "Ce message a été traité et ne nécessite plus d'être pris en charge" -#: agenda_culturel/models.py:2449 +#: agenda_culturel/models.py:2461 msgid "Comments on the message from the moderation team" msgstr "Commentaires sur ce message par l'équipe de modération" -#: agenda_culturel/models.py:2482 agenda_culturel/models.py:2657 +#: agenda_culturel/models.py:2494 agenda_culturel/models.py:2669 msgid "Recurrent import" msgstr "Import récurrent" -#: agenda_culturel/models.py:2483 +#: agenda_culturel/models.py:2495 msgid "Recurrent imports" msgstr "Imports récurrents" -#: agenda_culturel/models.py:2487 +#: agenda_culturel/models.py:2499 msgid "ical" msgstr "ical" -#: agenda_culturel/models.py:2488 +#: agenda_culturel/models.py:2500 msgid "ical no busy" msgstr "ical sans busy" -#: agenda_culturel/models.py:2489 +#: agenda_culturel/models.py:2501 msgid "ical no VC" msgstr "ical sans VC" -#: agenda_culturel/models.py:2490 +#: agenda_culturel/models.py:2502 msgid "ical naive timezone" msgstr "ical timezone naïve" -#: agenda_culturel/models.py:2491 +#: agenda_culturel/models.py:2503 msgid "lacoope.org" msgstr "lacoope.org" -#: agenda_culturel/models.py:2492 +#: agenda_culturel/models.py:2504 msgid "la comédie" msgstr "la comédie" -#: agenda_culturel/models.py:2493 +#: agenda_culturel/models.py:2505 msgid "le fotomat" msgstr "le fotomat" -#: agenda_culturel/models.py:2494 +#: agenda_culturel/models.py:2506 msgid "la puce à l'oreille" msgstr "la puce à loreille" -#: agenda_culturel/models.py:2495 +#: agenda_culturel/models.py:2507 msgid "Plugin wordpress MEC" msgstr "Plugin wordpress MEC" -#: agenda_culturel/models.py:2496 +#: agenda_culturel/models.py:2508 msgid "Événements d'une page FB" msgstr "Événements d'une page FB" -#: agenda_culturel/models.py:2497 +#: agenda_culturel/models.py:2509 msgid "Billetterie Clermont-Ferrand" msgstr "" -#: agenda_culturel/models.py:2498 +#: agenda_culturel/models.py:2510 msgid "Arachnée concert" msgstr "Arachnée concert" -#: agenda_culturel/models.py:2499 +#: agenda_culturel/models.py:2511 msgid "Le Rio" msgstr "Le Rio" -#: agenda_culturel/models.py:2500 +#: agenda_culturel/models.py:2512 msgid "La Raymonde" msgstr "La Raymone" -#: agenda_culturel/models.py:2501 +#: agenda_culturel/models.py:2513 msgid "Agenda apidae tourisme" msgstr "Agenda apidae tourisme" -#: agenda_culturel/models.py:2502 +#: agenda_culturel/models.py:2514 msgid "Agenda iguana (médiathèques)" msgstr "Agenda iguana (médiathèques)" -#: agenda_culturel/models.py:2503 +#: agenda_culturel/models.py:2515 msgid "Mille formes" msgstr "Mille Formes" -#: agenda_culturel/models.py:2504 +#: agenda_culturel/models.py:2516 msgid "Les Amis du Temps des Cerises" msgstr "Les Amis du Temps des Cerises" -#: agenda_culturel/models.py:2505 +#: agenda_culturel/models.py:2517 msgid "Mobilizon" msgstr "Mobilizon" -#: agenda_culturel/models.py:2508 +#: agenda_culturel/models.py:2520 msgid "simple" msgstr "simple" -#: agenda_culturel/models.py:2509 +#: agenda_culturel/models.py:2521 msgid "Headless Chromium" msgstr "chromium sans interface" -#: agenda_culturel/models.py:2512 +#: agenda_culturel/models.py:2524 msgid "Headless Chromium (pause)" msgstr "chromium sans interface (pause)" -#: agenda_culturel/models.py:2518 +#: agenda_culturel/models.py:2530 msgid "daily" msgstr "chaque jour" -#: agenda_culturel/models.py:2520 +#: agenda_culturel/models.py:2532 msgid "weekly" msgstr "chaque semaine" -#: agenda_culturel/models.py:2521 +#: agenda_culturel/models.py:2533 msgid "never" msgstr "jamais" -#: agenda_culturel/models.py:2526 +#: agenda_culturel/models.py:2538 msgid "" "Recurrent import name. Be careful to choose a name that is easy to " "understand, as it will be public and displayed on the sites About page." @@ -1046,151 +1053,151 @@ msgstr "" "Nom de l'import récurrent. Attention à choisir un nom compréhensible, car il " "sera public, et affiché sur la page à propos du site." -#: agenda_culturel/models.py:2533 +#: agenda_culturel/models.py:2545 msgid "Processor" msgstr "Processeur" -#: agenda_culturel/models.py:2539 +#: agenda_culturel/models.py:2551 msgid "Downloader" msgstr "Téléchargeur" -#: agenda_culturel/models.py:2546 +#: agenda_culturel/models.py:2558 msgid "Import recurrence" msgstr "Récurrence d'import" -#: agenda_culturel/models.py:2553 +#: agenda_culturel/models.py:2565 msgid "Source" msgstr "Source" -#: agenda_culturel/models.py:2554 +#: agenda_culturel/models.py:2566 msgid "URL of the source document" msgstr "URL du document source" -#: agenda_culturel/models.py:2559 +#: agenda_culturel/models.py:2571 msgid "Browsable url" msgstr "URL navigable" -#: agenda_culturel/models.py:2561 +#: agenda_culturel/models.py:2573 msgid "URL of the corresponding document that will be shown to visitors." msgstr "URL correspondant au document et qui sera montrée aux visiteurs" -#: agenda_culturel/models.py:2570 +#: agenda_culturel/models.py:2582 msgid "Status of each imported event (published or draft)" msgstr "Status de chaque événement importé (publié ou brouillon)" -#: agenda_culturel/models.py:2575 +#: agenda_culturel/models.py:2587 msgid "Address for each imported event" msgstr "Adresse de chaque événement importé" -#: agenda_culturel/models.py:2582 +#: agenda_culturel/models.py:2594 msgid "Force location" msgstr "Focer la localisation" -#: agenda_culturel/models.py:2583 +#: agenda_culturel/models.py:2595 msgid "force location even if another is detected." msgstr "Forcer la localisation même si une autre a été détectée." -#: agenda_culturel/models.py:2589 +#: agenda_culturel/models.py:2601 msgid "Organiser" msgstr "Organisateur" -#: agenda_culturel/models.py:2590 +#: agenda_culturel/models.py:2602 msgid "Organiser of each imported event" msgstr "Organisateur de chaque événement importé" -#: agenda_culturel/models.py:2600 +#: agenda_culturel/models.py:2612 msgid "Category of each imported event" msgstr "Catégorie de chaque événement importé" -#: agenda_culturel/models.py:2608 +#: agenda_culturel/models.py:2620 msgid "Tags for each imported event" msgstr "Étiquettes de chaque événement importé" -#: agenda_culturel/models.py:2609 +#: agenda_culturel/models.py:2621 msgid "A list of tags that describe each imported event." msgstr "Une liste d'étiquettes décrivant chaque événement importé" -#: agenda_culturel/models.py:2638 +#: agenda_culturel/models.py:2650 msgid "Running" msgstr "En cours" -#: agenda_culturel/models.py:2639 +#: agenda_culturel/models.py:2651 msgid "Canceled" msgstr "Annulé" -#: agenda_culturel/models.py:2640 +#: agenda_culturel/models.py:2652 msgid "Success" msgstr "Succès" -#: agenda_culturel/models.py:2641 +#: agenda_culturel/models.py:2653 msgid "Failed" msgstr "Erreur" -#: agenda_culturel/models.py:2644 +#: agenda_culturel/models.py:2656 msgid "Batch importation" msgstr "Importation par lot" -#: agenda_culturel/models.py:2645 +#: agenda_culturel/models.py:2657 msgid "Batch importations" msgstr "Importations par lot" -#: agenda_culturel/models.py:2658 +#: agenda_culturel/models.py:2670 msgid "Reference to the recurrent import processing" msgstr "Référence du processus d'import récurrent" -#: agenda_culturel/models.py:2666 +#: agenda_culturel/models.py:2678 msgid "URL (if not recurrent import)" msgstr "URL (si pas d'import récurrent)" -#: agenda_culturel/models.py:2667 +#: agenda_culturel/models.py:2679 msgid "Source URL if no RecurrentImport is associated." msgstr "URL source si aucun import récurrent n'est associé" -#: agenda_culturel/models.py:2682 +#: agenda_culturel/models.py:2694 msgid "Error message" msgstr "Votre message" -#: agenda_culturel/models.py:2686 +#: agenda_culturel/models.py:2698 msgid "Number of collected events" msgstr "Nombre d'événements collectés" -#: agenda_culturel/models.py:2689 +#: agenda_culturel/models.py:2701 msgid "Number of imported events" msgstr "Nombre d'événements importés" -#: agenda_culturel/models.py:2692 +#: agenda_culturel/models.py:2704 msgid "Number of updated events" msgstr "Nombre d'événements mis à jour" -#: agenda_culturel/models.py:2695 +#: agenda_culturel/models.py:2707 msgid "Number of removed events" msgstr "Nombre d'événements supprimés" -#: agenda_culturel/models.py:2703 +#: agenda_culturel/models.py:2715 msgid "Weight" msgstr "Poids" -#: agenda_culturel/models.py:2704 +#: agenda_culturel/models.py:2716 msgid "The lower is the weight, the earlier the filter is applied" msgstr "Plus le poids est léger, plus le filtre sera appliqué tôt" -#: agenda_culturel/models.py:2711 +#: agenda_culturel/models.py:2723 msgid "Category applied to the event" msgstr "Catégorie appliquée à l'événement" -#: agenda_culturel/models.py:2716 +#: agenda_culturel/models.py:2728 msgid "Contained in the title" msgstr "Contenu dans le titre" -#: agenda_culturel/models.py:2717 +#: agenda_culturel/models.py:2729 msgid "Text contained in the event title" msgstr "Texte contenu dans le titre de l'événement" -#: agenda_culturel/models.py:2723 +#: agenda_culturel/models.py:2735 msgid "Exact title extract" msgstr "Extrait exact du titre" -#: agenda_culturel/models.py:2725 +#: agenda_culturel/models.py:2737 msgid "" "If checked, the extract will be searched for in the title using the exact " "form (capitals, accents)." @@ -1198,19 +1205,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans le titre en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:2731 +#: agenda_culturel/models.py:2743 msgid "Contained in the description" msgstr "Contenu dans la description" -#: agenda_culturel/models.py:2732 +#: agenda_culturel/models.py:2744 msgid "Text contained in the description" msgstr "Texte contenu dans la description" -#: agenda_culturel/models.py:2738 +#: agenda_culturel/models.py:2750 msgid "Exact description extract" msgstr "Extrait exact de description" -#: agenda_culturel/models.py:2740 +#: agenda_culturel/models.py:2752 msgid "" "If checked, the extract will be searched for in the description using the " "exact form (capitals, accents)." @@ -1218,19 +1225,19 @@ msgstr "" "Si coché, l'extrait sera recherché dans la description en utilisant la forme " "exacte (majuscules, accents)" -#: agenda_culturel/models.py:2746 +#: agenda_culturel/models.py:2758 msgid "Contained in the location" msgstr "Contenu dans la localisation" -#: agenda_culturel/models.py:2747 +#: agenda_culturel/models.py:2759 msgid "Text contained in the event location" msgstr "Texte contenu dans la localisation de l'événement" -#: agenda_culturel/models.py:2753 +#: agenda_culturel/models.py:2765 msgid "Exact location extract" msgstr "Extrait exact de localisation" -#: agenda_culturel/models.py:2755 +#: agenda_culturel/models.py:2767 msgid "" "If checked, the extract will be searched for in the location using the exact " "form (capitals, accents)." @@ -1238,15 +1245,15 @@ msgstr "" "Si coché, l'extrait sera recherché dans la localisation en utilisant la " "forme exacte (majuscules, accents)" -#: agenda_culturel/models.py:2763 +#: agenda_culturel/models.py:2775 msgid "Location from place" msgstr "Localisation depuis le lieu" -#: agenda_culturel/models.py:2772 +#: agenda_culturel/models.py:2784 msgid "Categorisation rule" msgstr "Règle de catégorisation" -#: agenda_culturel/models.py:2773 +#: agenda_culturel/models.py:2785 msgid "Categorisation rules" msgstr "Règles de catégorisation" diff --git a/src/agenda_culturel/migrations/0154_tag_message.py b/src/agenda_culturel/migrations/0154_tag_message.py new file mode 100644 index 0000000..bb8adbc --- /dev/null +++ b/src/agenda_culturel/migrations/0154_tag_message.py @@ -0,0 +1,24 @@ +# Generated by Django 4.2.19 on 2025-03-14 12:23 + +from django.db import migrations +import django_ckeditor_5.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ("agenda_culturel", "0153_event_local_event"), + ] + + operations = [ + migrations.AddField( + model_name="tag", + name="message", + field=django_ckeditor_5.fields.CKEditor5Field( + blank=True, + help_text="Message displayed to the user on each event associated with this tag.", + null=True, + verbose_name="Message", + ), + ), + ] diff --git a/src/agenda_culturel/models.py b/src/agenda_culturel/models.py index 5f5f3cc..ca6f6f0 100644 --- a/src/agenda_culturel/models.py +++ b/src/agenda_culturel/models.py @@ -198,6 +198,15 @@ class Tag(models.Model): null=True, ) + message = CKEditor5Field( + verbose_name=_("Message"), + help_text=_( + "Message displayed to the user on each event associated with this tag." + ), + blank=True, + null=True, + ) + principal = models.BooleanField( verbose_name=_("Principal"), help_text=_( @@ -1051,6 +1060,15 @@ class Event(models.Model): ) return result + def tag_messages(self): + if self.tags is None: + return [] + return Tag.objects.filter( + Q(name__in=self.tags) + & Q(message__isnull=False) + & ~Q(message__in=["", "

", "

 

"]) + ).values("message") + def get_all_tags(sort=True): cursor = connection.cursor() raw_query = """ diff --git a/src/agenda_culturel/static/style.scss b/src/agenda_culturel/static/style.scss index b7056fa..2253667 100644 --- a/src/agenda_culturel/static/style.scss +++ b/src/agenda_culturel/static/style.scss @@ -751,6 +751,10 @@ $yellow-900: #616918 !default; background-position: center left var(--form-element-spacing-vertical); // use vertical for icon left align background-size: $iconsize auto; padding-left: calc(var(--form-element-spacing-vertical) * 2 + #{$iconsize}); + + p:last-child { + margin-bottom: 0; + } } .message.danger, .message.error { --background-color: #{$red-50}; diff --git a/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html b/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html index 755cf2c..7f58ae1 100644 --- a/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html +++ b/src/agenda_culturel/templates/agenda_culturel/single-event/event-single-inc.html @@ -152,6 +152,7 @@
+ {% for message in event.tag_messages %}
{{ message.message|safe }}
{% endfor %} {% if event.has_image_url %}
{{ event.image_alt }}