[ADD] application: clock, translation, formatting, displayed name
The screens need one clock, one translation mechanism and one way to
format and name, or each component grows its own. horloge.js is the only
code that reads time and arms timers, injected so tests drive it.
traduction.js keys texts by domain, in two families of tables, raises on a
missing key and never shows a raw key; libelles/ splits the label table by
domain. format.js formats numbers and dates in French, and personnes.js
composes the displayed name the frozen labels use. Nothing persists
between sessions.
Checked: 1773 node and 43 browser tests.
--- FR ---
[ADD] application : horloge, traduction, mise en forme, nom affiché
Les écrans exigent une horloge, un mécanisme de traduction et une façon de
mettre en forme et de nommer, sans quoi chaque composant ferait les siens.
horloge.js est le seul code qui lit l'heure et arme des minuteries, injecté
pour que les épreuves le pilotent. traduction.js range les textes par
domaine, en deux familles de tables, lève sur une clé absente et ne montre
jamais une clé brute ; libelles/ découpe la table des libellés par domaine.
format.js met en forme nombres et dates en français, et personnes.js
compose le nom affiché qu'emploient les libellés figés. Rien ne persiste
d'une séance à l'autre.
Vérifié : 1773 node et 43 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 02:33:39 -04:00
|
|
|
// © 2026 TechnoLibre (http://www.technolibre.ca)
|
|
|
|
|
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
|
|
|
|
|
|
|
|
|
|
// Les libellés de l'import d'une liste : aperçu et rapport (§ 14.6). Chaque
|
[ADD] interface: event list, open event, participants, import, plan
The working screens of an evening. The home screen lists the events of
the working folder, asks its question, loads demos, copies, renames,
imports and deletes, and shows what the trash holds. An open event frames
its mode, offers Modifier, Débloquer and a confirmed lock takeover, and
shows its warnings. Participants get a grid, a form and a file; an import
goes through a preview and a report; tables, the default and tours have
their screens; the plan draws tables, chairs, empty seats and names.
Checked: 2342 node, 356 browser, 60 node-long; the Electron start check.
--- FR ---
[ADD] interface : liste, événement, participants, import, tables, plan
Les écrans de travail d'une soirée. L'accueil liste les événements du
dossier de travail, pose sa question, charge les démonstrations, copie,
renomme, importe et supprime, et montre ce que tient la corbeille. Un
événement ouvert encadre son mode, offre Modifier, Débloquer et une
reprise de verrou confirmée, et montre ses avertissements. Les
participants ont une grille, un formulaire et une fiche ; un import passe
par un aperçu et un rapport ; tables, défaut et tours ont leurs écrans ;
le plan dessine tables, chaises, sièges vides et noms.
Vérifié : 2342 node, 356 navigateur, 60 node-long ; démarrage d'Electron.
Assisted-by: Claude Opus 5.5
2026-10-07 08:12:27 -04:00
|
|
|
// clé commence par « import. ». Un nombre, un nom ou un rang s'affiche dans
|
|
|
|
|
// son propre nœud de texte : les libellés qui le suivent ne reçoivent que ce
|
|
|
|
|
// qui accorde le nom au compte.
|
|
|
|
|
|
|
|
|
|
// Le singulier jusqu'à un, le pluriel au-delà, comme le veut le français.
|
|
|
|
|
const accorde = (n, singulier, pluriel) => (n <= 1 ? singulier : pluriel);
|
|
|
|
|
|
|
|
|
|
export const TABLE = new Map([
|
|
|
|
|
// --- La section et ses commandes (§ 10.1, § 10.2) ----------------------------
|
|
|
|
|
[
|
|
|
|
|
'import.consigne',
|
|
|
|
|
'Choisissez un fichier CSV ou déposez-le sur la fenêtre ; une plage collée dans la grille des participants arrive ici. ' +
|
|
|
|
|
"Rien ne s'importe avant l'aperçu.",
|
|
|
|
|
],
|
|
|
|
|
['import.commande.choisirFichier', 'Choisir un fichier CSV\u{2026}'],
|
|
|
|
|
['import.commande.importer', 'Importer'],
|
|
|
|
|
['import.commande.fermerApercu', "Fermer l'aperçu"],
|
|
|
|
|
['import.commande.ordreDeLaGrille', "Lire les colonnes dans l'ordre de la grille"],
|
|
|
|
|
['import.commande.enregistrerRefus', 'Enregistrer les lignes refusées'],
|
|
|
|
|
['import.commande.fermerRapport', 'Fermer le rapport'],
|
|
|
|
|
['import.refusEnregistres', 'Lignes refusées enregistrées :'],
|
|
|
|
|
|
|
|
|
|
// --- Le mode de l'import (§ 10.1) -------------------------------------------
|
|
|
|
|
['import.mode.titre', "Mode de l'import"],
|
|
|
|
|
['import.mode.ajouter', 'Ajouter'],
|
|
|
|
|
['import.mode.mettreAJour', 'Mettre à jour'],
|
|
|
|
|
['import.mode.remplacer', 'Remplacer'],
|
|
|
|
|
|
|
|
|
|
// --- L'aperçu : source, encodage, séparateur ---------------------------------
|
|
|
|
|
['import.apercu.titre', 'Aperçu'],
|
|
|
|
|
['import.apercu.fichier', 'Fichier'],
|
|
|
|
|
['import.apercu.collage', 'Texte collé'],
|
|
|
|
|
['import.apercu.encodage', 'Encodage'],
|
|
|
|
|
['import.apercu.separateur', 'Séparateur'],
|
|
|
|
|
['import.encodage.utf8Marque', 'UTF-8 avec marque'],
|
|
|
|
|
['import.encodage.utf16le', 'UTF-16 LE'],
|
|
|
|
|
['import.encodage.utf16be', 'UTF-16 BE'],
|
|
|
|
|
['import.encodage.utf8', 'UTF-8'],
|
|
|
|
|
['import.encodage.windows1252', 'windows-1252'],
|
|
|
|
|
['import.separateur.pointVirgule', 'point-virgule'],
|
|
|
|
|
['import.separateur.virgule', 'virgule'],
|
|
|
|
|
['import.separateur.tabulation', 'tabulation'],
|
|
|
|
|
['import.separateur.uneColonne', 'une seule colonne'],
|
|
|
|
|
|
|
|
|
|
// --- L'aperçu : les colonnes et leur association (§ 10.1) --------------------
|
|
|
|
|
['import.apercu.colonnes', 'Colonnes'],
|
|
|
|
|
['import.apercu.entete', 'En-tête'],
|
|
|
|
|
['import.apercu.devient', 'Devient'],
|
|
|
|
|
['import.champ.nom', 'nom'],
|
|
|
|
|
['import.champ.prenom', 'prénom'],
|
|
|
|
|
['import.champ.appartenance', 'appartenance'],
|
|
|
|
|
['import.champ.courriel', 'courriel'],
|
|
|
|
|
['import.champ.titrePressenti', 'titre pressenti'],
|
|
|
|
|
['import.champ.exclu', 'exclu'],
|
|
|
|
|
['import.champ.notes', 'notes'],
|
|
|
|
|
['import.exclu.oui', 'oui'],
|
|
|
|
|
['import.exclu.non', 'non'],
|
|
|
|
|
['import.colonne.nonReconnue', 'non reconnue : ignorée'],
|
|
|
|
|
['import.colonne.aTrancher', 'à trancher'],
|
|
|
|
|
['import.colonne.ecartee', 'écartée par le choix'],
|
|
|
|
|
['import.ambiguite.question', 'Plusieurs colonnes répondent au même champ. Laquelle vaut :'],
|
|
|
|
|
|
|
|
|
|
// --- L'aperçu : les lignes ---------------------------------------------------
|
|
|
|
|
['import.apercu.valides', ({ n }) => accorde(n, 'ligne valide', 'lignes valides')],
|
|
|
|
|
['import.apercu.refusees', 'Lignes refusées'],
|
|
|
|
|
['import.apercu.ligne', 'Ligne'],
|
|
|
|
|
['import.apercu.motif', 'Motif'],
|
|
|
|
|
['import.apercu.fusions', 'Orthographes fondues en une appartenance'],
|
|
|
|
|
['import.apercu.orthographeLignes', ({ n }) => accorde(n, 'ligne', 'lignes')],
|
|
|
|
|
['import.apercu.affichee', 'affichée :'],
|
|
|
|
|
['import.apercu.doublons', 'Doublons signalés, jamais fusionnés'],
|
|
|
|
|
['import.apercu.doublonLignes', 'lignes'],
|
|
|
|
|
['import.apercu.doublonExistants', 'déjà dans la liste :'],
|
|
|
|
|
['import.apercu.homonymes', "Ajoutées à côté d'une personne de même nom"],
|
|
|
|
|
['import.apercu.multilignes', 'Cellules sur plusieurs lignes qui portent le séparateur : à vérifier'],
|
|
|
|
|
|
|
|
|
|
// --- Les refus globaux : le remède (§ 10.1) ---------------------------------
|
|
|
|
|
['import.remede.caractereNulCollage', 'Retirez le caractère nul du texte collé, ou importez le fichier réenregistré en UTF-8.'],
|
|
|
|
|
['import.remede.aucunEntete', "Ajoutez une ligne d'en-tête qui nomme les colonnes, « nom » au moins."],
|
|
|
|
|
[
|
|
|
|
|
'import.remede.aucunEnteteCollage',
|
|
|
|
|
"Ajoutez une ligne d'en-tête qui nomme les colonnes, ou lisez les colonnes dans l'ordre de la grille.",
|
|
|
|
|
],
|
|
|
|
|
['import.remede.nomNonAssocie', 'Nommez « nom » la colonne des noms.'],
|
|
|
|
|
['import.remede.aucuneLigneValide', 'Corrigez les lignes refusées, listées avec leur motif.'],
|
|
|
|
|
[
|
|
|
|
|
'import.remede.guillemetOuvert',
|
|
|
|
|
({ ligne }) => `Fermez le guillemet ouvert${Number.isInteger(ligne) ? ` à la ligne ${ligne}` : ''}.`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'import.remede.separateurIntrouvable',
|
|
|
|
|
'Séparez les colonnes par « ; », « , » ou une tabulation, en même nombre à chaque ligne.',
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'import.remede.separateurIntrouvableCollage',
|
|
|
|
|
"Séparez les colonnes par « ; », « , » ou une tabulation, ou lisez la colonne dans l'ordre de la grille : " +
|
|
|
|
|
'chaque ligne devient un nom.',
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- La fenêtre de « Remplacer » (§ 10.1) ------------------------------------
|
|
|
|
|
['import.remplacer.titre', 'Remplacer la liste des participants'],
|
|
|
|
|
[
|
|
|
|
|
'import.remplacer.participants',
|
|
|
|
|
({ n }) => `${n} ${accorde(n, 'personne sera supprimée', 'personnes seront supprimées')}`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'import.remplacer.reservations',
|
|
|
|
|
({ n }) => `${n} ${accorde(n, 'réservation sera supprimée', 'réservations seront supprimées')}`,
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'import.remplacer.titres',
|
|
|
|
|
({ n }) =>
|
|
|
|
|
`${n} ${accorde(n, 'titre perdra la réservation qui le pourvoit', 'titres perdront la réservation qui les pourvoit')}, ` +
|
|
|
|
|
'à un tour au moins',
|
|
|
|
|
],
|
|
|
|
|
[
|
|
|
|
|
'import.remplacer.propositions',
|
|
|
|
|
({ n }) => `${n} ${accorde(n, 'proposition deviendra périmée', 'propositions deviendront périmées')}`,
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
// --- Le rapport (§ 10.1) ---------------------------------------------------
|
|
|
|
|
['import.rapport.titre', "Rapport d'import"],
|
|
|
|
|
['import.rapport.ajoutes', ({ n }) => accorde(n, 'personne ajoutée', 'personnes ajoutées')],
|
|
|
|
|
['import.rapport.misAJour', ({ n }) => accorde(n, 'personne mise à jour', 'personnes mises à jour')],
|
|
|
|
|
['import.rapport.inchanges', ({ n }) => accorde(n, 'personne inchangée', 'personnes inchangées')],
|
|
|
|
|
['import.rapport.retires', ({ n }) => accorde(n, 'personne retirée', 'personnes retirées')],
|
|
|
|
|
['import.rapport.reservationsRetirees', ({ n }) => accorde(n, 'réservation retirée', 'réservations retirées')],
|
|
|
|
|
['import.rapport.rienEcrit', "Rien n'a changé dans la liste : seules des lignes refusées restent à lire."],
|
|
|
|
|
['import.rapport.designees', 'désignées :'],
|
|
|
|
|
]);
|