v3 : interface Svelte — accueil, groupes, lecteur du texte en vigueur, panneau contextuel, éditeur à assistant, trustinWallet

- Accueil sobre, menu complet à gauche (Décisions, Docs de référence, Mandats,
  Protocoles), intro demandée, quatre sections, connexion Ğ1.
- Lecteur : texte en vigueur en Literata, actions contextuelles par article
  (le vote, propositions, proposer), propositions en cours sous la « surface »
  avec leur niveau d'eau, aperçus « si les bien cotées passent » / « si tout
  passe », langue du texte fr/en/es (traductions éditoriales).
- Panneau : vote pour/contre, seuil et formule (MathML), inertie et son
  changement (voté en inertie +), coquille sans vote, traduction, signalement
  de contradiction, historique des corrections.
- trustinWallet (/acces) : groupes et membres, invitations à usage unique,
  administrateurs, retours d'usage.
- Contrôles : vitest (markdown, catalogues, anti-lexique), Playwright C1–C10 + M1.
- Sections du seed portées jusqu'à l'écran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-21 02:58:34 +02:00
co-authored by Claude Opus 5.5
parent 67ddee28b2
commit 7a022dd35e
66 changed files with 7771 additions and 15 deletions
+315
View File
@@ -0,0 +1,315 @@
import type { Messages } from './fr';
export const en: Messages = {
'app.name': 'libreDecision',
'app.skip': 'Skip to content',
'nav.label': 'Toolbox',
'nav.home': 'Home',
'nav.decisions': 'Decisions',
'nav.docs': 'Reference documents',
'nav.mandates': 'Mandates',
'nav.protocols': 'Protocols',
'nav.soon': 'coming soon',
'nav.groups': 'My groups',
'nav.access': 'Access',
'nav.access.hint': 'trustinWallet',
'nav.feedback': 'Give feedback',
'nav.signin': 'Sign in',
'nav.signout': 'Sign out',
'nav.mood.toNight': 'Night mood',
'nav.mood.toStone': 'Stone mood',
'nav.lang': 'Language',
'nav.menu': 'Menu',
'nav.close': 'Close',
'home.title': 'Making collective decisions possible',
'home.subtitle': 'depending on the context, processes and methods, a toolbox',
'home.decisions': 'A guided path to choose the right decision methods, and to keep the decision log.',
'home.docs': 'Commitment act, license, charter, constitution: living texts, always open for voting.',
'home.mandates': 'Create and revoke any kind of mandate.',
'home.protocols': 'Workflows to organize without a statutory body: rotating roles and technical automations.',
'home.open': 'open',
'home.soon': 'coming soon',
'home.signin': 'Sign in with your Ğ1 key',
'home.signin.note': 'The same access as the Monnaie libre forum: you sign with Ğecko, no password needed.',
'home.continue': 'Open my groups',
'signin.title': 'Sign in',
'signin.g1': 'Sign in with Ğ1',
'signin.g1.how': "You'll be sent to connect.monnaie-libre.fr, the sign-in service of the Monnaie libre forum. There you approve the sign-in in Ğecko (link or QR code), then come back here. No password and no key is ever passed to us.",
'signin.g1.members': 'For members of the Ğ1 web of trust only.',
'signin.g1.pending': "Ğ1 sign-in is on its way: libreDecision's registration with connect.monnaie-libre.fr is in progress. Meanwhile, you get in with an invitation link.",
'signin.invite': 'Got an invitation link? Just open it: it signs you in.',
'signin.dev': 'Development sign-in',
'signin.dev.name': 'Name',
'signin.dev.admin': 'access administrator',
'signin.dev.go': 'Enter',
'signin.error.refus': 'The sign-in was declined on connect.monnaie-libre.fr.',
'signin.error.etat': 'The sign-in expired or came from another browser. Start again from this browser.',
'signin.error.incomplet': 'The response from connect.monnaie-libre.fr was incomplete. Start again.',
'signin.error.echange': "connect.monnaie-libre.fr isn't responding. Try again in a moment.",
'signin.error.interne': 'Sign-in failed on our side. Try again in a moment.',
'invite.title': 'Invitation',
'invite.working': 'Signing in…',
'invite.invalid': 'This invitation link is no longer valid: it has already been used or it has expired. Ask the person who sent it to you for a new link.',
'invite.missing': 'This link is incomplete. Open the whole invitation link, exactly as you received it.',
'groups.title': 'My groups',
'groups.same.key': 'Groups that use the same key',
'groups.locked': 'Members only',
'groups.locked.long': 'This group opens to its members. Ask a trustinWallet administrator for access.',
'groups.test': 'For testing',
'groups.open': 'Open',
'groups.empty': 'No group is visible yet.',
'group.tools': 'Tools',
'group.tool.soon': 'This tool is coming later.',
'group.docs.empty': 'No reference documents in this group yet.',
'docs.title': 'Reference documents',
'docs.inForce.one': '{n} article in force',
'docs.inForce.other': '{n} articles in force',
'docs.open.one': '{n} open proposal',
'docs.open.other': '{n} open proposals',
'doc.view.label': 'Read',
'doc.view.inforce': 'In force',
'doc.view.wellrated': 'If well-rated ones pass',
'doc.view.all': 'If everything passes',
'doc.view.wellrated.note': 'Preview: the text as it would be if the well-rated proposals came into force. Nothing is adopted.',
'doc.view.all.note': 'Preview: the text as it would be if all proposals came into force, even those with little support. Nothing is adopted.',
'doc.view.empty': 'No proposal changes the text in this preview.',
'doc.mark.added': 'added',
'doc.mark.replaced': 'changed',
'doc.mark.removed': 'removed',
'doc.lang.label': 'Text language',
'doc.lang.translation': 'Editorial translation, not voted on. The authoritative text is in French.',
'doc.lang.original': 'Read the original',
'doc.lang.stale': 'translation needs review',
'doc.lang.missing': 'not translated yet',
'doc.seed': 'seed a minima',
'doc.seed.long': 'Came into force without a vote, so as not to start from a blank page. It remains open for voting: 0 votes so far.',
'doc.confirmed': 'confirmed by vote',
'doc.adopted': 'adopted on {date}',
'doc.action.vote': 'Voting',
'doc.action.proposals': 'Proposals',
'doc.action.propose': 'Propose a change',
'doc.empty': 'No article is in force. The proposals below move up as soon as they reach their threshold.',
'doc.published': 'Published to the text repository',
'doc.publish.pending': 'Publication pending',
'deep.title': 'Open proposals',
'deep.note': 'Not in force yet. Each one moves up as soon as it reaches its threshold: at least {floor} votes in favor, then the majority its inertia requires.',
'deep.new': 'Propose a new article',
'deep.drafts': 'Your drafts',
'deep.drafts.note': 'Not submitted to vote. Only you can see them.',
'deep.rival': 'would replace “{title}”',
'deep.addition': 'new article',
'deep.removal': 'removal of “{title}”',
'deep.inertia': 'inertia: {level}',
'deep.blocked': 'blocked',
'deep.mine': 'your proposal',
'deep.stale': 'needs reconfirming',
'deep.wellrated': 'well-rated',
'deep.filter.all': 'All',
'deep.filter.wellrated': 'Well-rated',
'deep.filter.mine': 'Mine',
'deep.none': 'No proposals in this filter.',
'deep.variant': 'variant {label}',
'section.introduction': 'Introduction',
'section.fondamental': 'Fundamental commitments',
'section.technique': 'Technical commitments',
'section.conclusion': 'Conclusion',
'section.annexe': 'Annexes',
'section.formule': 'Voting formula',
'section.inertie': 'Inertia',
'section.ordonnancement': 'Ordering',
'tally.short': '{for} for · {against} against',
'tally.required': 'Threshold: {n} votes in favor',
'tally.missing.one': '{n} more vote in favor needed.',
'tally.missing.other': '{n} more votes in favor needed.',
'tally.reached': 'Threshold reached.',
'tally.level': 'Level: {pct}% of the threshold',
'inertia.low': 'low inertia',
'inertia.standard': 'standard inertia',
'inertia.high': 'high inertia',
'inertia.max': 'maximum inertia',
'inertia.level.low': 'low',
'inertia.level.standard': 'standard',
'inertia.level.high': 'high',
'inertia.level.max': 'maximum',
'panel.vote': 'Voting',
'panel.proposals': 'Proposals',
'panel.propose': 'Propose',
'panel.close': 'Close panel',
'panel.inforce': 'In force',
'panel.proposal': 'Proposal',
'panel.by': 'proposed by {name}',
'panel.seed.origin': 'text from the seed',
'panel.changes': 'View changes',
'panel.text': 'View text',
'vote.yours': 'Your vote',
'vote.for': 'For',
'vote.against': 'Against',
'vote.retract': 'Withdraw my vote',
'vote.saved': 'Vote saved.',
'vote.retracted': 'Vote withdrawn.',
'vote.stale': 'The text has changed in substance since you voted: your vote no longer counts until you reconfirm it.',
'vote.reconfirm': 'Reconfirm: {choice}',
'vote.private': 'Nobody sees your vote: only the totals are visible.',
'vote.blocked': "A contradiction flag is holding it back: it can't come into force while the flag stands.",
'vote.entered': '“{title}” has come into force.',
'vote.entered.remove': '“{title}” has been removed from the text in force.',
'vote.entered.inertia': 'The inertia of “{title}” has changed.',
'vote.closed': 'This version is no longer open for voting.',
'inertia.title': 'Inertia',
'inertia.explain': 'The higher the inertia, the more votes it takes to change this text when few people vote.',
'inertia.change': 'Propose an inertia change',
'inertia.change.to': 'New inertia',
'inertia.change.note': 'An inertia change is itself voted on with the next inertia up: {level}.',
'inertia.change.submit': 'Submit to vote',
'inertia.change.open': 'Inertia change in progress: to {level}',
'formula.title': 'The threshold formula',
'formula.intro': 'The number of votes in favor required, R, depends on turnout:',
'formula.W': 'W — electorate: {n} ({source})',
'formula.W.wot': 'members of the Ğ1 web of trust',
'formula.W.group': 'group members',
'formula.T': 'T — votes cast: {n}',
'formula.M': 'M — majority at full turnout: {n}%',
'formula.G': 'G — gradient: {n}',
'formula.B': 'B — base: {n}',
'formula.C': 'C — minimum votes in favor: {n}',
'formula.R': 'R — current threshold: {n} votes in favor',
'formula.reading': 'At low turnout, near-unanimity is needed; when everyone votes, majority M is enough. Nothing passes with fewer than C votes in favor.',
'history.title': 'Corrections',
'history.initial': 'initial text',
'history.typo': 'typo fixed',
'history.substantive': 'substantive change (votes to reconfirm)',
'history.by': 'by {name}',
'typo.title': 'Fix a typo',
'typo.note': 'Accents, punctuation, typos: the fix applies without a vote, with its author and its diff. A change in meaning goes through a proposal.',
'typo.save': 'Save the fix',
'typo.done': 'Typo fixed, votes untouched.',
'typo.substantive': 'This edit affects the meaning: propose it as a change.',
'typo.asProposal': 'Make it a proposal',
'signal.title': 'Contradictions',
'signal.none': 'No flags.',
'signal.add': 'Flag a contradiction',
'signal.target': 'Contradicts',
'signal.reason': 'How these two texts contradict each other',
'signal.send': 'Flag',
'signal.sent': 'Flag saved.',
'signal.note': "While a flag stands, these two texts can't be in force together. Its author lifts it; a substantive change makes it lapse.",
'signal.lift': 'Lift',
'signal.lifted': 'lifted',
'signal.lifted.revision': 'lapsed: the text changed',
'signal.by': 'by {name}',
'propose.mode.replace': 'Change this text',
'propose.mode.remove': 'Remove this article',
'propose.mode.new': 'New article',
'propose.after': 'Place after',
'propose.after.end': 'at the end',
'propose.title': 'Title',
'propose.body': 'Text',
'propose.remove.note': 'A removal proposal is voted on like any other; if it passes, the article leaves the text in force.',
'propose.draft': 'Save draft',
'propose.submit': 'Submit to vote',
'propose.drafted': 'Draft saved.',
'propose.submitted': 'Proposal submitted to vote.',
'propose.rule': "While it's a draft, you edit it freely. Once it's submitted, a typo can be fixed without touching the votes; a substantive change asks voters to reconfirm.",
'propose.edit': 'Edit',
'propose.withdraw': 'Withdraw my proposal',
'propose.withdrawn': 'Proposal withdrawn.',
'propose.saved.typo': 'Fix saved, the votes stand.',
'propose.saved.substantive': 'New version saved: voters will have to reconfirm.',
'assist.title': 'Assistant',
'assist.quiet': 'Nothing to report: one proposal, one decision.',
'assist.split': 'This text seems to carry {n} decisions. One proposal = one decision: split it?',
'assist.split.do': 'Split into {n} drafts',
'assist.split.done': 'Split into {n} drafts.',
'assist.similar': 'Close to “{title}”{where}.',
'assist.similar.inForce': ' (in force)',
'assist.similar.variant': 'Make it a variant of this article',
'assist.long': 'Long text ({n} characters): a short article is easier to vote on.',
'translate.title': 'Translate ({lang})',
'translate.save': 'Save translation',
'translate.saved': 'Translation saved.',
'translate.note': 'Translations are not voted on. They switch to “needs review” when the French text changes in substance.',
'feedback.title': 'Give feedback',
'feedback.prompt': 'What you did, what you expected, what happened.',
'feedback.send': 'Send feedback',
'feedback.sent': 'Feedback sent. Thank you.',
'feedback.context': 'The page address, language and screen size are attached.',
'access.title': 'trustinWallet — access',
'access.intro': 'Who opens which group. Monnaie libre opens by itself to members of the Ğ1 web of trust; other groups open one by one.',
'access.groups': 'Groups',
'access.members.none': 'No members granted access.',
'access.members.wot': '+ all members of the Ğ1 web of trust',
'access.grant': 'Grant',
'access.revoke': 'Remove',
'access.choose': 'Choose an identity',
'access.invitations': 'Invitations',
'access.invite.label': "Who it's for",
'access.invite.groups': 'Groups opened by the link',
'access.invite.admin': 'access administrator',
'access.invite.create': 'Create invitation link',
'access.invite.link': "Invitation link, single use, valid for 14 days. It won't be shown again: copy it now.",
'access.invite.copy': 'Copy link',
'access.invite.copied': 'Link copied.',
'access.invite.cancel': 'Cancel',
'access.invite.pending': 'Pending',
'access.identities': 'Identities',
'access.admin': 'administrator',
'access.admin.give': 'Make administrator',
'access.admin.take': 'Remove role',
'access.kind.g1': 'Ğ1',
'access.kind.invite': 'invitation',
'access.kind.dev': 'dev',
'access.member': 'web of trust member',
'access.feedback': 'Feedback',
'access.feedback.none': 'No feedback.',
'access.feedback.seen': 'Seen',
'access.feedback.done': 'Handled',
'access.denied': 'Access management is for trustinWallet administrators only.',
'soon.title': 'Coming soon',
'soon.body': 'This tool is coming later. Tools open one at a time: reference documents first.',
'error.unauthenticated': 'Sign in to continue.',
'error.forbidden': "You don't have access to this page.",
'error.not_found': "This page doesn't exist, or isn't visible to you.",
'error.network': "The server isn't responding. Check your connection and try again.",
'error.internal': 'Something failed on our side. Try again in a moment.',
'error.title': 'The title is empty or too long (120 characters max).',
'error.body': 'The text is empty or too long (4,000 characters max).',
'error.reason': 'Say in a few words how these texts contradict each other (10 to 600 characters).',
'error.substantive_not_author': "This edit affects the meaning: only the proposal's author can make it. Propose your own version.",
'error.substantive_in_force': 'This edit affects the meaning: propose it as a change.',
'error.same_unit': "These two texts target the same article: they can't be in force together anyway.",
'error.last_admin': 'At least one administrator must remain.',
'error.g1_not_configured': "Ğ1 sign-in isn't active yet.",
'error.invitation_invalid': 'This invitation link is no longer valid.',
'error.retry': 'Try again',
'common.cancel': 'Cancel',
'common.close': 'Close',
'common.save': 'Save',
'common.loading': 'Loading…',
'common.back': 'Back',
};