Aller au contenu

Modifier la langue et les messages#

Il est possible de personnaliser tous les textes générés par le thÚme :

  • la chaĂźne de caractĂšres utilisĂ©e pour sĂ©parer le code utilisateur des tests publics dans les Ă©diteurs de code (voir TestsToken pour les contraintes spĂ©cifiques Ă  ce cas),
  • les info-bulles des diffĂ©rents boutons liĂ©s au thĂšme,
  • les messages affichĂ©s dans les terminaux,
  • les noms des admonitions (pour les solutions et remarques des macros {{ IDE(...) }}, ou les macros {{ figures() }}),
  • ...

Les changements peuvent ĂȘtre ponctuels, mais cela peut aller jusqu'Ă  dĂ©finir une autre langue !

Langue utilisée#

Le thÚme propose tous ses messages en différentes langues : de, en et fr.
La langue par défaut est fr.

Comme pour mkdocs-material la langue du thÚme est modifiée dans le fichier mkdocs.yml :

theme:
    language: fr
fr
theme:
    language: en
en


Add a new language to the theme?

If you want another language to be added to the theme, the process would be the following:

  1. Create a fork of the project.
  2. Create a pyodide_mkdocs_theme/pyodide_macros/messages/xx_lang.py file by copying en_lang.py in the same directory, then:

    • Change the class name to LangXx
    • Translate all the string arguments of each property of the class
    • Translate also their docstrings
  3. Create a copy of the pyodide_mkdocs_theme/scripts/en directory at pyodide_mkdocs_theme/scripts/xx then translate the files in pyodide_mkdocs_theme/scripts/xx/docs:

    • For xx/docs/index.md: no need to translate both multi_qcm calls, one will be enough.
    • For xx/docs/exo.py: don't forget to translate the function and variable names.
  4. Create an issue on the PMT's repository explaining your request and giving the link to the forked repository.
    Alternatively, the individual files could be provided directly in the issue, if you don't want to fork the repository itself.

Personnalisations#

Guide rapide#

Il est possible de modifier tous ces messages en mettant à profit la définition de macros personnalisées.
L'idée générale est la suivante :

  1. Récupérez le code python de personnalisation, via la commande appropriée des scripts du thÚme ou tout en bas de cette page.

  2. Placez ce code dans un fichier de macros personnalisées (voir comment faire plus bas, selon qu'il y a déjà des macros personnalisées dans votre projet ou non).

  3. Modifiez les messages qui vous concernent. Vous pouvez supprimer les entrées qui ne nécessitent pas de modification.

  4. Pour les infos-bulles (objets Tip), pensez Ă  adapter leur largeur (en em) via le premier argument.

  5. "Et voilĂ  !"

Récupérer le code#

Les commandes ci-dessous permettent d'afficher dans la console le contenu du code python nécessaire pour modifier tous les messages utilisés automatiquement par le thÚme.

Par exemple:

  • En français, par dĂ©faut :

    python -m pyodide_mkdocs_theme --lang
    


  • Dans une langue spĂ©cifique, en utilisant l'abrĂ©viation appropriĂ©e ( de, en ou fr) :

    python -m pyodide_mkdocs_theme --lang en
    


  • Il est aussi possible de crĂ©er directement un fichier contenant le code complet, plutĂŽt que de l'afficher dans la console :

    python -m pyodide_mkdocs_theme --lang --file "main.py"
    

    Argument --file

    Si l'argument --file pointe vers un fichier qui existe déjà, ce ficher sera remplacé sans avertissement.

Intégrer le code de personnalisation au projet#

La méthode d'intégration dépend de la préexistence ou non de macros personnalisées dans votre projet.


  • Projet sans macros personnalisĂ©es

    Dans ce cas, il suffit d'enregistrer le code de personnalisation dans un fichier main.py Ă  la racine du projet.
    Le plus simple est alors d'utiliser la commande appropriée des scripts du thÚme en utilisant l'argument --file.


  • Projet avec un fichier main.py existant

    Le plus simple est alors d'ajouter les imports ainsi que le contenu de la fonction define_env du code de personnalisation dans votre fichier main.py.


  • Projet avec un package de macros personnalisĂ©es

    Si vous disposez d'un package de macros, vous saurez sans doute adapter votre package...

    Remplacer le fichier main.py par une bibliothĂšque

    Si vous souhaitez passer d'un fichier main.py à un package, les grandes lignes de l'opération sont les suivantes :

    1. Créer un dossier à la racine du projet.

    2. Dans le ficher mkdocs.yml, ajouter le nom du dossier de macros personnalisées dans la configuration du plugin :

      Utiliser un package pour les macros personnalisées
      plugins:
          - pyodide_macros:
              module_name: package_name
      


    3. Ajouter un fichier __init__.py dans ce dossier (ceci transforme le dossier en package python).

    4. Ajouter une fonction define_env(env:PyodideMacrosPlugin) Ă  ce fichier __init__.py.
      Toutes les macros doivent ĂȘtre dĂ©finies depuis l'intĂ©rieur de cette fonction, comme pour le fichier main.py.



    Les fonctions dĂ©finissant les macros peuvent aussi ĂȘtre dĂ©clarĂ©es dans d'autres fichiers de la bibliothĂšque, puis importĂ©es pour ĂȘtre enregistrĂ©es en tant que macros.

    Il y a de nombreuses approches possibles pour réaliser ceci. En voici une ci-dessous :

    • Import des fonctions depuis le fichier __init__.py
    • EnregistrĂ©es en tant que macros en executant env.macro(function_importĂ©e) depuis l'intĂ©rieur de la fonction define_env.
    Exemple de fichier __init__.py
    from pyodide_mkdocs_theme.pyodide_macros import PyodideMacrosPlugin
    from . import my_file1, my_file2
    
    def define_env(env:PyodideMacrosPlugin):
    
        env.macro(my_file1.macro1)      # my_file1 contient une fonction "macro1"
        env.macro(my_file1.macro2)
        ...
    
        # Ou crĂ©er les macros directement ici (mais le package n'a alors plus d'intĂ©rĂȘt...)
        @env.macro
        def macroX(...):
            ...
    


    Si une de ces macros nécessite d'accéder à la variable env, on peut ruser de différentes façons :

    La façon de procéder la plus naturelle, en combinant des fichiers contenant une fonction define_env(env), comme un fichier main.py isolé le ferait :

    └── `macros_perso`
        ├── __init__.py
        ├── module1.py
        └── module2.py
    

    module1.py

    def define_env(env):
    
        @env.macro
        def my_macro():
            ...
            return ...
    

    __init__.py

    from . import module1, module2
    
    def define_env(env):
    
        for module in (module1, module2):
            module.define_env(env)
    

    Une alternative, moins naturelle, utilisant des "functions factories". L'intĂ©rĂȘt pourrait ĂȘtre de voir les noms de toutes les macros personnalisĂ©es depuis le fichier __init__.py.

    La structure de fichiers est la mĂȘme :

    └── `macros_perso`
        ├── __init__.py
        └── module1.py
    

    module1.py

    def macro1(env):
        def macro1():
            # impĂ©rativement le mĂȘme nom !
            return ... # avec env
        return macro1 # la fonction interne
    

    __init__.py

    from .module import macro1
    
    def define_env(env):
    
        env.macro( macro1(env) )
    

Détail des messages #

Editor infos


Gestion du séparateur entre le code utilisateur et les tests publics, ainsi que de l'info-bulle du bouton pour activer/désactiver ces tests.



tests: Tr = TestsToken('\n# Tests\n') class-attribute instance-attribute #

Séparateur placé entre le code utilisateur et les tests publics.

  • Les sauts de lignes situĂ©s au dĂ©but ou Ă  la fin indiquent le nombre de lignes vides avant ou aprĂšs le texte lui-mĂȘme.
  • Le sĂ©parateur lui-mĂȘme doit commencer par # et avoir au moins 6 caractĂšres (hors espaces).

comments: Tr = Tip(17, '(Dés-)Active le code aprÚs la ligne <code>{tests}</code> (insensible à la casse)', 'Ctrl+I') class-attribute instance-attribute #

Info-bulle pour le bouton permettant d'activer ou désactiver les tests publics. La chaßne utilisée doit contenir {tests} car le contenu de TestsToken.msg y sera inséré.

split_screen: Tr = Tip(23, 'Entrer ou sortir du mode "deux colonnes"<br>(<kbd>Alt+:</kbd> ; <kbd>Ctrl</kbd> pour inverser les colonnes)') class-attribute instance-attribute #

Info-bulle pour le bouton permettant d'activer ou désactiver le mode deux colonnes.

split_mode_placeholder: Tr = Msg("Éditeur dans l'autre colonne") class-attribute instance-attribute #

Message affiché à la place de l'IDE placé en mode deux colonnes, à sa position d'origine dans la page.

full_screen: Tr = Tip(10, 'Entrer ou sortir du mode "plein écran"', 'Esc') class-attribute instance-attribute #

Info-bulle pour le bouton permettant d'activer ou désactiver le mode plein écran.

refresh: Tr = Msg("Une version plus récente du code existe.\nVeuillez copier vos éventuelles modifications puis réinitialiser l'IDE.", format='warning') class-attribute instance-attribute #

Message affiché dans le terminal lorsque le code contenu dans le localStorage de l'utilisateur est plus vieux que celui du dernier pipeline.

Terminal messages


Boutons du terminal et messages usuels vus par l'utilisateur dans les terminaux, lorsque du code est exécuté.



feedback: Tr = Tip(19, 'Tronquer ou non le feedback dans les terminaux (sortie standard & stacktrace / relancer le code pour appliquer)') class-attribute instance-attribute #

Info-bulle du bouton contrÎlant le "niveau de feedback" affiché dans le terminal

wrap_term: Tr = Tip(19, "Si activĂ©, le texte copiĂ© dans le terminal est joint sur une seule ligne avant d'ĂȘtre copiĂ© dans le presse-papier") class-attribute instance-attribute #

Info-bulle du bouton indiquant si le texte copiĂ© depuis le terminal est join anat d'ĂȘtre copiĂ© ou non.

run_script: Tr = Msg('Script lancé...', format='info') class-attribute instance-attribute #

Message annonçant le début des exécutions (pyodide).

install_start: Tr = Msg('Installation de paquets python. Ceci peut prendre un certain temps...', format='info') class-attribute instance-attribute #

Message affiché dans la console avant le chargement de micropip, en vue d'installer des modules manquants.

install_done: Tr = Msg('Installations terminées !', format='info') class-attribute instance-attribute #

Message affiché lorsque les installation de paquets par micropip sont finies.

Terminal messages


Construction des messages lorsqu'une étape des tests est passée, que ce soit les tests publics ou les validations.



secret_tests: Tr = Msg('Tests secrets', format='info') class-attribute instance-attribute #

Nom donné aux tests exécutés à la derniÚre étape des validations.

public_tests: Tr = Msg('Tests publics', format='info') class-attribute instance-attribute #

Nom donné aux tests publics originaux, exécuté en étape 2 des validations.

validation: Tr = Msg('Validation - ', format='info') class-attribute instance-attribute #

Nom donné en début de ligne de feedback les étapes passées avec succÚs lors des validations.

editor_code: Tr = Msg('Éditeur', format='info') class-attribute instance-attribute #

Nom désignant le contenu de l'éditeur.

success_msg: Tr = Msg('OK', format='success') class-attribute instance-attribute #

Message annonçant qu'une étape des tests est validée.

success_msg_no_tests: Tr = Msg('Terminé sans erreur.', format='info') class-attribute instance-attribute #

Message annonçant la fin des exécutions, lorsqu'il n'y a ni bouton de validation, ni section tests.

unforgettable: Tr = Msg("N'oubliez pas de faire une validation !", format='warning') class-attribute instance-attribute #

Message affiché à la fin des tests publics, si aucune erreur n'a été rencontrée et qu'une validation est disponible.

Terminal messages

Ces chaßnes de caractÚres servent à construire les messages dans les terminaux lorsque le code de l'utilisateur passe les tests ou bien a consommé tous les essais disponibles.

Évùnement Canevas du message
SuccĂšs {success_head} emoji - {success_head_extra}
{success_tail} {reveal}
Échec {fail_head} - {reveal} {fail_tail}

Dans les deux cas, la chaßne reveal est construite en fonction de la présence ou l'absence de correction et remarques :

Correction Remarques reveal
Oui Non {reveal_corr}
Oui Oui {reveal_corr} {reveal_join} {reveal_rem}
Non Oui {reveal_rem}



success_head: Tr = Msg('Bravo !', format='success') class-attribute instance-attribute #

EntĂȘte du message de succĂšs (gras, italique, en vert)

success_tail: Tr = Msg('Pensez Ă  lire') class-attribute instance-attribute #

Fin du message de succĂšs.

fail_head: Tr = Msg('Dommage !', format='warning') class-attribute instance-attribute #

EntĂȘte du message d'Ă©chec (gras, italique, en orange)

reveal_corr: Tr = Msg('le corrigé') class-attribute instance-attribute #

Bout de phrase annonçant l'existence d'une correction.

reveal_join: Tr = Msg('et') class-attribute instance-attribute #

Conjonction de coordination joignant reveal_corr et reveal_rem, quand correction et remarques sont présentes.

reveal_rem: Tr = Msg('les commentaires') class-attribute instance-attribute #

Bout de phrase annonçant l'existence de remarques.

success_head_extra: Tr = Msg('Vous avez réussi tous les tests !') class-attribute instance-attribute #

Fin du message annonçant un succÚs.

fail_tail: Tr = MsgPlural('est maintenant disponible', 'sont maintenant disponibles') class-attribute instance-attribute #

Fin du message annonçant un échec.

Admonition example


Chaßnes de caractÚres utilisées pour construire l'admonition contenant la solution et les remarques (si elles existent. Ne concerne que les remarques "non visibles", donc pas les contenus des fichiers {exo}_VIS_REM.md).



title_corr: Tr = Msg('Solution') class-attribute instance-attribute #

Utilisé pour construire le titre de l'admonition contenant la correction et/ou les remarques, sous les IDEs.

title_rem: Tr = Msg('Remarques') class-attribute instance-attribute #

Utilisé pour construire le titre de l'admonition contenant la correction et/ou les remarques, sous les IDEs.

corr: Tr = Msg('🐍 Proposition de correction') class-attribute instance-attribute #

Titre du bloc de code contenant la correction d'un IDE, dans l'admonition "correction & remarques".

rem: Tr = Msg('Remarques') class-attribute instance-attribute #

Titre (équivalent <h3>) annonçant le début des remarques, dans l'admonition "correction & remarques"

Editor infos

py_btn: Tr = Tip(9, 'Exécuter le code') class-attribute instance-attribute #

Info-bulle d'un bouton isolé, permettant de lancer un code python.

play: Tr = Tip(9, 'Exécuter le code', 'Ctrl+S') class-attribute instance-attribute #

Info-bulle du bouton pour lancer les tests publics.

check: Tr = Tip(9, "Valider<br><kbd>Ctrl</kbd>+<kbd>Enter</kbd><br>(Clic droit pour l'historique)") class-attribute instance-attribute #

Info-bulle du bouton pour lancer les validations.

download: Tr = Tip(0, 'Télécharger') class-attribute instance-attribute #

Info-bulle du bouton pour télécharger le contenu d'un éditeur.

upload: Tr = Tip(0, 'Téléverser') class-attribute instance-attribute #

Info-bulle du bouton pour remplacer le contenu d'un éditeur avec un fichier stocké en local.

restart: Tr = Tip(0, "Réinitialiser l'éditeur") class-attribute instance-attribute #

Info-bulle du bouton réinitialisant le contenu d'un éditeur.

save: Tr = Tip(0, 'Sauvegarder dans le navigateur') class-attribute instance-attribute #

Info-bulle du bouton pour enregistrer le contenu d'un éditeur dans le localStorage du navigateur.

zip: Tr = Tip(14, 'Archiver les codes des IDEs exportables de la page') class-attribute instance-attribute #

Info-bulle du bouton permettant de télécharger un zip avec tous les contenus des éditeurs.

corr_btn: Tr = Tip(0, 'Tester la correction (serve)') class-attribute instance-attribute #

Info-bulle du bouton pour tester le code de la correction (uniquement durant mkdocs serve).

show: Tr = Tip(0, 'Afficher corr & REMs') class-attribute instance-attribute #

Info-bulle du bouton pour révéler les solutions & REMs (uniquement durant mkdocs serve).

attempts_left: Tr = Msg('Évaluations restantes') class-attribute instance-attribute #

Texte annonçant le nombres d'essais de validation restant.

Messages spécifiques à la page de tests de tous les IDEs de la documentation.

tests_done: Tr = Msg('Tests terminés', 'info') class-attribute instance-attribute #

Message apparaissant Ă  la fin des tests de tous les IDEs, dans le terminal

test_ides: Tr = Tip(7, 'Lance tous les tests...') class-attribute instance-attribute #

Info-bulle de la page de test des IDEs.

test_stop: Tr = Tip(6, 'ArrĂȘte les tests') class-attribute instance-attribute #

Info-bulle de la page de test des IDEs.

test_1_ide: Tr = Tip(7, 'Lance ce test') class-attribute instance-attribute #

Info-bulle de la page de test des IDEs.

load_ide: Tr = Tip(10, "Configure l'IDE avec ces données") class-attribute instance-attribute #

Info-bulle de la page de test des IDEs.

qcm example

qcm_title: Tr = MsgPlural('Question') class-attribute instance-attribute #

Titre utilisé par défaut pour les admonitions contenant les qcms (si pas d'argument renseigné dans l'appel de la macro multi_qcm).

qcm_mask_tip: Tr = Tip(11, 'Les réponses resteront cachées...') class-attribute instance-attribute #

Info-bulle affichée au survol du masque, pour les qcms dont les réponses ne sont pas révélées.

qcm_check_tip: Tr = Tip(11, 'Vérifier les réponses') class-attribute instance-attribute #

Info-bulle du bouton de validation des réponses des qcms.

qcm_redo_tip: Tr = Tip(9, 'Recommencer') class-attribute instance-attribute #

Info-bulle du bouton de réinitialisation des qcms.

figure_text: Tr = Msg('Votre tracé sera ici') class-attribute instance-attribute #

Texte affiché avent qu'une figure ne soit dessinée (voir à propos des dessins faits avec matplotlib et la macro figure(...)).

figure_admo_title: Tr = Msg('Votre figure') class-attribute instance-attribute #

Titre donné aux admonitions contenant des "figures" (voir à propos des dessins faits avec matplotlib et la macro figure(...)).

p5_start: Tr = Tip(0, "Démarre l'animation") class-attribute instance-attribute #

Info-bulle du bouton pour démarrer la boucle d'évÚnement des animations p5.

p5_stop: Tr = Tip(0, "ArrĂȘte l'animation") class-attribute instance-attribute #

Info-bulle du bouton pour stopper la boucle d'évÚnement des animations p5.

p5_step: Tr = Tip(0, "Avance d'une image") class-attribute instance-attribute #

Info-bulle du bouton pour stopper la boucle d'évÚnement des animations p5.

tip_trash: Tr = Tip(15, 'Supprimer du navigateur les codes enregistrés pour {site_name}') class-attribute instance-attribute #

Info-bulle du bouton de pour supprimer les données stockées dans le navigateur (la poubelle en haut à cÎté de la barre de recherche). Le nom du site (site_name dans mkdocs.yml) est automatiquement intégré dans la phrase avec "{site_name}".

picker_failure: Tr = Msg('Veuillez cliquer sur la page entre deux utilisations des raccourcis clavier ou utiliser un bouton, afin de pouvoir téléverser un fichier.') class-attribute instance-attribute #

Message s'affichant dans le navigateur quand l'utilisateur essaie de lancer plusieurs fois un code utilisant pyodide_uploader_async via un raccourci clavier sans autre interaction avec la page entre les deux : ceci n'est pas autorisé par les navigateurs.

Nota: les utilisateur de navigateurs non compatibles avec HTMLInputElement.showPicker n'auront jamais cette information.

zip_ask_for_names: Tr = Msg('Veuillez préciser votre/vos noms (chaßne vide interdite) :') class-attribute instance-attribute #

Message affichĂ© dans la fenĂȘtre avant la crĂ©ation d'une archive zip des contenues des IDEs exportables, si l'auteur requiĂšre l'ajout du nom du ou des utilisateurs.

Les classes utilisées#

Msg(msg: str, format: Optional[str] = None) dataclass #

A simple message to display in the application.

Parameters:

Name Type Description Default
msg str

Message to use

required
format Optional[str]

Formatting to use in the terminal. See lower.

None

MsgPlural(msg: str, plural: str = '', format: Optional[str] = None) dataclass #

A message that could be used in singular or plural version at runtime.

Parameters:

Name Type Description Default
msg str

Message to use

required
plural str

If not given, msg+"s" is used as plural.

''
format Optional[str]

Formatting to use in the terminal. See lower.

None


À propos du formatage des messages

Voici les différentes options de formatage disponibles.

Remarques

  • La couleur par dĂ©faut des terminaux est celle dĂ©finie par la palette de couleur du site (dans le fichier mkdocs.yml:theme.palette).
  • Les couleurs utilisĂ©es dans les exemples ci-contre ne sont pas exactement les mĂȘmes que celles utilisĂ©es dans les terminaux, mais permettent d'avoir une bonne idĂ©e du rendu qui sera obtenu.
Nom Rendu
"error" Rouge + gras
"info" Gris + italique
"italic" Italique
"none" Défaut
"stress" Gras
"success" Vert + gras + italique
"warning" Orange + gras + italique


Tip(em: int, msg: str, kbd: str = '') dataclass #

Data for tooltips.

Parameters:

Name Type Description Default
em int

Width of the tooltip element, in em units (if 0, use automatic width).

required
msg str

Tooltip message.

required
kbd str

Keyboard shortcut (as "Ctrl+I", for example). Informational only (no impact on the behaviors)

''

If a kbd combination is present, it will be automatically added in a new line after the tooltip msg.

TestsToken(msg: str, as_pattern: re.Pattern = TMP_PATTERN) dataclass #

Specific delimiter used to separate the user's code from the public tests in an editor. Leading and trailing new lines used here will reflect on the editor content and will match the number of additional empty lines before or after the token itself.

Because this token is also be converted to a regex used in various places, it has to follow some conventions. Ignoring leading and trailing new lines:

  • The string must begin with #.
  • The string must not contain new line characters anymore.
  • Ignoring inner spaces, the token string must be at least 6 characters long.

Parameters:

Name Type Description Default
msg str

Separator to use (with leading and trailing new lines).

required

Raises:

Type Description
BuildError

If one of the above conditions is not fulfilled.

Code de personnalisation#

from pyodide_mkdocs_theme.pyodide_macros import (
    PyodideMacrosPlugin,
    Msg, MsgPlural, TestsToken, Tip,
)


def define_env(env:PyodideMacrosPlugin):
    """ The customization has to be done at macro definition time.
        You could paste the code inside this function into your own main.py (or the
        equivalent package if you use a package instead of a single file). If you don't
        use personal macros so far, copy the full code into a `main.py` file at the root
        of your project (note: NOT in the docs_dir!).

        NOTE: you can also completely remove this file if you don't want to use personal
              macros or customize the messages in the built documentation.

        * Change whatever string you want.
        * Remove the entries you don't want to modify
        * Do not change the keyboard shortcuts for the Tip objects: the values are for
          informational purpose only.
        * See the documentation for more details about which string is used for what
          purpose, and any constraints on the arguments:
          https://frederic-zinelli.gitlab.io/pyodide-mkdocs-theme/custom/messages/#messages-details

        ---

        The signatures for the various objects defined below are the following:

        ```python
        Msg(msg:str)

        MsgPlural(msg:str, plural:str="")

        Tip(width_in_em:int, msg:str, kbd:str=None)

        TestsToken(token_str:str)
        ```
    """

    env.lang.overload({

    # Editors:
        "tests":      TestsToken("\n# Tests\n"),
        "comments":   Tip(17, "(Dés-)Active le code aprÚs la ligne <code>{tests}</code> "
                             "(insensible Ă  la casse)", "Ctrl+I"),
        "split_screen": Tip(23, 'Entrer ou sortir du mode "deux colonnes"<br>(<kbd>Alt+:</kbd> '
                               '; <kbd>Ctrl</kbd> pour inverser les colonnes)'),
        "split_mode_placeholder": Msg("Éditeur dans l'autre colonne"),
        "full_screen": Tip(10, 'Entrer ou sortir du mode "plein écran"', "Esc"),


    # Terminals
        "feedback":      Tip(19, "Tronquer ou non le feedback dans les terminaux (sortie standard"
                                " & stacktrace / relancer le code pour appliquer)"),
        "wrap_term":     Tip(19, "Si activé, le texte copié dans le terminal est joint sur une "
                                "seule ligne avant d'ĂȘtre copiĂ© dans le presse-papier"),


    # Runtime feedback
        "run_script":    Msg("Script lancé...", format='info'),
        "install_start": Msg("Installation de paquets python. Ceci peut prendre un certain temps...", format='info'),
        "install_done":  Msg("Installations terminées !", format='info'),
        "refresh":       Msg("Une version plus récente du code existe.\nVeuillez copier vos "
                            "éventuelles modifications puis réinitialiser l'IDE.", format='warning'),


        "validation":    Msg("Validation - ", format='info'),
        "editor_code":   Msg("Éditeur", format='info'),
        "public_tests":  Msg("Tests publics", format='info'),
        "secret_tests":  Msg("Tests secrets", format='info'),
        "success_msg":   Msg("OK", format='success'),
        "success_msg_no_tests": Msg("Terminé sans erreur.", format='info'),
        "unforgettable": Msg("N'oubliez pas de faire une validation !", format='warning'),


    # Terminals: validation success/failure messages
        "success_head":  Msg("Bravo !", format='success'),
        "success_head_extra":  Msg("Vous avez réussi tous les tests !"),
        "success_tail":  Msg("Pensez Ă  lire"),
        "fail_head":     Msg("Dommage !", format='warning'),
        "reveal_corr":   Msg("le corrigé"),
        "reveal_join":   Msg("et"),
        "reveal_rem":    Msg("les commentaires"),
        "fail_tail":     MsgPlural("est maintenant disponible", "sont maintenant disponibles"),


    # Corr / rems admonition:
        "title_corr":    Msg('Solution'),
        "title_rem":     Msg('Remarques'),
        "corr":          Msg('🐍 Proposition de correction'),
        "rem":           Msg('Remarques'),


    # Buttons, IDEs buttons & counter:
        "py_btn":        Tip(9, "Exécuter le code"),
        "play":          Tip(9, "Exécuter le code", "Ctrl+S"),
        "check":         Tip(9, "Valider<br><kbd>Ctrl</kbd>+<kbd>Enter</kbd><br>(Clic droit pour l'historique)"),
        "download":      Tip(0, "Télécharger"),
        "upload":        Tip(0, "Téléverser"),
        "restart":       Tip(0, "Réinitialiser l'éditeur"),
        "save":          Tip(0, "Sauvegarder dans le navigateur"),
        "zip":           Tip(14, "Archiver les codes des IDEs exportables de la page"),
        "corr_btn":      Tip(0, "Tester la correction (serve)"),
        "show":          Tip(0, "Afficher corr & REMs"),
        "attempts_left": Msg("Évaluations restantes"),


    # Testing
        "tests_done":    Msg("Tests terminés", 'info'),
        "test_ides":     Tip(7, "Lance tous les tests..."),
        "test_stop":     Tip(6, "ArrĂȘte les tests"),
        "test_1_ide":    Tip(7, "Lance ce test"),
        "load_ide":      Tip(10, "Configure l'IDE avec ces données"),



    # QCMS
        "qcm_title":     MsgPlural("Question"),
        "qcm_mask_tip":  Tip(11, "Les réponses resteront cachées..."),
        "qcm_check_tip": Tip(11, "Vérifier les réponses"),
        "qcm_redo_tip":  Tip(9,  "Recommencer"),


    # Others
        "tip_trash": Tip(15, "Supprimer du navigateur les codes enregistrés pour {site_name}"),


        "figure_admo_title": Msg("Votre figure"),
        "figure_text":       Msg("Votre tracé sera ici"),
        "p5_start":          Tip(0, "Démarre l'animation"),
        "p5_stop":           Tip(0, "ArrĂȘte l'animation"),
        "p5_step":           Tip(0, "Avance d'une image"),


        "picker_failure": Msg(
            "Veuillez cliquer sur la page entre deux utilisations des raccourcis clavier ou "
            "utiliser un bouton, afin de pouvoir téléverser un fichier."
        ),

        "zip_ask_for_names": Msg("Veuillez préciser votre/vos noms (chaßne vide interdite) :")
    })