Spreadsheet-UX op een echte relationele engine

main

Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.

14.3 kB Ruw bestand
import type { MessageCatalog } from './entry';

/**
 * The shell around the grid: the top bar and its menus, the sidebar, the
 * workspace picker and settings, and the people and agent-key dialogs.
 */
export const chrome = {
  /* Said by the top bar and the picker alike. */
  'chrome.signOut': { en: 'Sign out', nl: 'Uitloggen' },

  /* Top bar */
  'topbar.workspace': { en: 'Workspace', nl: 'Werkruimte' },
  'topbar.demoReadOnly': { en: 'demo · read-only', nl: 'demo · alleen-lezen' },
  'topbar.searchIn': {
    en: (table: string) => `Search ${table}`,
    nl: (table: string) => `Zoeken in ${table}`,
  },
  'topbar.searchCurrentTable': { en: 'Search the current table', nl: 'Zoek in de huidige tabel' },
  'topbar.clearSearch': { en: 'Clear search', nl: 'Zoekopdracht wissen' },
  'topbar.undoAction': {
    en: (label: string) => `Undo ${label}`,
    nl: (label: string) => `${label} ongedaan maken`,
  },
  'topbar.nothingToUndo': { en: 'Nothing to undo', nl: 'Niets om ongedaan te maken' },
  'topbar.redo': { en: 'Redo', nl: 'Opnieuw' },
  'topbar.redoAction': {
    en: (label: string) => `Redo ${label}`,
    nl: (label: string) => `${label} opnieuw uitvoeren`,
  },
  'topbar.nothingToRedo': { en: 'Nothing to redo', nl: 'Niets om opnieuw te doen' },
  'topbar.auditTrail': { en: 'Audit trail', nl: 'Audittrail' },
  'topbar.createYourOwn': { en: 'Create your own', nl: 'Maak er zelf een' },
  'topbar.account': { en: 'Account', nl: 'Account' },
  'topbar.workspaceSettings': { en: 'Workspace settings…', nl: 'Werkruimte-instellingen…' },
  'topbar.people': { en: 'People…', nl: 'Mensen…' },
  'topbar.agentKeys': { en: 'Agent keys…', nl: 'Agentsleutels…' },
  'topbar.planAndBilling': { en: 'Plan and billing…', nl: 'Abonnement en facturering…' },
  'topbar.usage': { en: 'Usage…', nl: 'Gebruik…' },
  'topbar.switchTo': {
    en: (name: string) => `Switch to ${name}`,
    nl: (name: string) => `Wisselen naar ${name}`,
  },
  'topbar.allWorkspaces': { en: 'All workspaces…', nl: 'Alle werkruimtes…' },
  'topbar.yourAccount': { en: 'Your account…', nl: 'Je account…' },

  /* Sidebar */
  'sidebar.tablesAndViews': { en: 'Tables and views', nl: 'Tabellen en weergaven' },
  'sidebar.tables': { en: 'Tables', nl: 'Tabellen' },
  'sidebar.importSpreadsheet': { en: 'Import a spreadsheet', nl: 'Spreadsheet importeren' },
  'sidebar.newTable': { en: 'New table', nl: 'Nieuwe tabel' },
  'sidebar.workflowRules': { en: 'Workflow rules', nl: 'Workflowregels' },
  'sidebar.ruleAction': {
    en: (column: string, value: string) => `→ set ${column} = ${value}`,
    nl: (column: string, value: string) => `→ zet ${column} = ${value}`,
  },
  'sidebar.ruleDisableTitle': {
    en: 'Stop this rule from firing',
    nl: 'Deze regel niet meer laten afgaan',
  },
  'sidebar.ruleEnableTitle': {
    en: 'Let this rule fire again',
    nl: 'Deze regel weer laten afgaan',
  },
  'sidebar.disable': { en: 'Disable', nl: 'Uitschakelen' },
  'sidebar.enable': { en: 'Enable', nl: 'Inschakelen' },
  'sidebar.tableMenuLabel': {
    en: (label: string) => `${label} table`,
    nl: (label: string) => `Tabel ${label}`,
  },
  'sidebar.viewMenuLabel': {
    en: (name: string) => `${name} view`,
    nl: (name: string) => `Weergave ${name}`,
  },
  'sidebar.copyTableName': { en: 'Copy table name', nl: 'Tabelnaam kopiëren' },
  'sidebar.addColumn': { en: 'Add column…', nl: 'Kolom toevoegen…' },
  'sidebar.importIntoTable': { en: 'Import into this table…', nl: 'In deze tabel importeren…' },
  'sidebar.tidyTable': { en: 'Tighten the columns…', nl: 'Kolommen aanscherpen…' },
  'sidebar.editTable': { en: 'Edit table…', nl: 'Tabel bewerken…' },
  'sidebar.deleteTable': { en: 'Delete table', nl: 'Tabel verwijderen' },
  'sidebar.renameView': { en: 'Rename view…', nl: 'Weergave hernoemen…' },
  'sidebar.renameViewPrompt': { en: 'Rename this view', nl: 'Deze weergave hernoemen' },
  'sidebar.duplicateView': { en: 'Duplicate view', nl: 'Weergave dupliceren' },
  'sidebar.deleteView': { en: 'Delete view', nl: 'Weergave verwijderen' },
  'sidebar.deleteViewConfirm': {
    en: (name: string) => `Delete the view “${name}”?`,
    nl: (name: string) => `De weergave “${name}” verwijderen?`,
  },
  'sidebar.viewCopyName': {
    en: (name: string) => `${name} copy`,
    nl: (name: string) => `${name} kopie`,
  },
  'sidebar.copiedTo': {
    en: (name: string) => `Copied to “${name}”.`,
    nl: (name: string) => `Gekopieerd naar “${name}”.`,
  },

  /* Workspace picker */
  'picker.choose': { en: 'choose a workspace', nl: 'kies een werkruimte' },
  'picker.first': { en: 'your first workspace', nl: 'je eerste werkruimte' },
  'picker.unknownAfter': {
    en: (email: string) =>
      ` is not a workspace you can open. If a colleague sent it, ask them to invite ${email}.`,
    nl: (email: string) =>
      ` is geen werkruimte die je kunt openen. Heeft een collega hem gestuurd, vraag ze dan om ${email} uit te nodigen.`,
  },
  'picker.workspaceName': { en: 'Workspace name', nl: 'Naam van de werkruimte' },
  'picker.address': { en: 'Address:', nl: 'Adres:' },
  'picker.creating': { en: 'Creating…', nl: 'Aanmaken…' },
  'picker.createIt': { en: 'Create it', nl: 'Maak hem aan' },
  'picker.new': { en: 'New workspace', nl: 'Nieuwe werkruimte' },
  'picker.demoStructure': { en: 'Demo structure', nl: 'Demostructuur' },
  'picker.demoStructureHint': {
    en: 'the tables, views and groups of a small bike workshop — linked the way real work is',
    nl: 'de tabellen, views en groepen van een kleine fietswerkplaats — gekoppeld zoals echt werk',
  },
  'picker.demoData': { en: 'With demo data', nl: 'Met demodata' },
  'picker.demoDataHint': {
    en: 'rows too, so the formulas and rollups have something to say',
    nl: 'ook rijen, zodat de formules en rollups iets te zeggen hebben',
  },

  /* Workspace settings */
  'workspace.title': { en: 'Workspace', nl: 'Werkruimte' },
  'workspace.updated': { en: 'Workspace updated.', nl: 'Werkruimte bijgewerkt.' },
  'workspace.leaveConfirm': {
    en: (name: string) => `Leave ${name}? You will need a new invitation to come back.`,
    nl: (name: string) =>
      `${name} verlaten? Je hebt een nieuwe uitnodiging nodig om terug te komen.`,
  },
  'workspace.address': { en: 'Address', nl: 'Adres' },
  'workspace.addressHintBefore': {
    en: 'Everyone here reaches it at ',
    nl: 'Iedereen hier bereikt hem via ',
  },
  'workspace.addressHintAfter': {
    en: '. Changing it breaks links people have saved.',
    nl: '. Als je het wijzigt, werken opgeslagen links niet meer.',
  },
  'workspace.currency': { en: 'Currency', nl: 'Valuta' },
  'workspace.currencyHint': {
    en: 'What every currency column here is read in. It changes how amounts are shown, not the numbers themselves — nothing is converted.',
    nl: 'Waarin elke valutakolom hier gelezen wordt. Het verandert hoe bedragen getoond worden, niet de getallen zelf — er wordt niets omgerekend.',
  },
  'workspace.language': { en: 'Language', nl: 'Taal' },
  'workspace.languageHint': {
    en: 'The language this workspace speaks, for everyone who opens it — and how its numbers and dates are written.',
    nl: 'De taal die deze werkruimte spreekt, voor iedereen die haar opent — en hoe de getallen en datums erin geschreven worden.',
  },
  'workspace.exportHead': { en: 'Take the data with you', nl: 'Neem de data mee' },
  'workspace.exportHint': {
    en: 'One SQLite file holding every table, view, rule and audit line in this workspace, plus the list of who is in it. It opens in any SQLite tool.',
    nl: 'Eén SQLite-bestand met elke tabel, weergave, regel en auditregel in deze werkruimte, plus de lijst van wie erin zit. Het opent in elk SQLite-programma.',
  },
  'workspace.download': { en: 'Download the workspace', nl: 'Werkruimte downloaden' },
  'workspace.leavingHead': { en: 'Leaving', nl: 'Vertrekken' },
  'workspace.leavingHint': {
    en: 'Leaving removes your access to this workspace. Your account and any other workspaces stay as they are.',
    nl: 'Vertrekken haalt je toegang tot deze werkruimte weg. Je account en je andere werkruimtes blijven zoals ze zijn.',
  },
  'workspace.leave': {
    en: (name: string) => `Leave ${name}`,
    nl: (name: string) => `${name} verlaten`,
  },
  'workspace.deleteHead': { en: 'Delete this workspace', nl: 'Deze werkruimte verwijderen' },
  'workspace.deleteHintBefore': {
    en: 'This deletes the database file. Every table, row and audit line goes with it, and nothing here is recoverable. Type ',
    nl: 'Dit verwijdert het databasebestand. Elke tabel, rij en auditregel gaat mee, en niets hiervan is terug te halen. Typ ',
  },
  'workspace.deleteHintAfter': { en: ' to confirm.', nl: ' om te bevestigen.' },
  'workspace.deleteConfirmAria': {
    en: 'Type the workspace address to confirm deletion',
    nl: 'Typ het adres van de werkruimte om verwijdering te bevestigen',
  },
  'workspace.deleteIt': { en: 'Delete it', nl: 'Verwijder hem' },

  /* People */
  'people.title': {
    en: (name: string) => `People in ${name}`,
    nl: (name: string) => `Mensen in ${name}`,
  },
  'people.thisWorkspace': { en: 'this workspace', nl: 'deze werkruimte' },
  'people.roleHelp.viewer': {
    en: 'Read everything. Change nothing.',
    nl: 'Leest alles. Verandert niets.',
  },
  'people.roleHelp.editor': {
    en: 'Add, edit and delete rows; save views.',
    nl: 'Rijen toevoegen, bewerken en verwijderen; weergaven opslaan.',
  },
  'people.roleHelp.admin': {
    en: 'Everything, plus the schema and who is here.',
    nl: 'Alles, plus het schema en wie hier is.',
  },
  'people.inviteSomeone': { en: 'Invite someone', nl: 'Iemand uitnodigen' },
  'people.linkCopied': {
    en: 'Invitation link copied. Send it to them yourself.',
    nl: 'Uitnodigingslink gekopieerd. Stuur hem zelf door.',
  },
  'people.removeConfirm': {
    en: (email: string) =>
      `Remove ${email} from this workspace? Their Wellformed account and their other workspaces are untouched.`,
    nl: (email: string) =>
      `${email} uit deze werkruimte verwijderen? Hun Wellformed-account en hun andere werkruimtes blijven ongemoeid.`,
  },
  'people.lastSeen': { en: 'Last seen', nl: 'Laatst gezien' },
  'people.you': { en: 'you', nl: 'jij' },
  'people.never': { en: 'never', nl: 'nooit' },
  'people.roleFor': {
    en: (email: string) => `Role for ${email}`,
    nl: (email: string) => `Rol voor ${email}`,
  },
  'people.pendingHead': { en: 'Invited, not joined yet', nl: 'Uitgenodigd, nog geen lid' },
  'people.expires': {
    en: (date: string) => `expires ${date}`,
    nl: (date: string) => `verloopt ${date}`,
  },
  'people.revoke': { en: 'Revoke', nl: 'Intrekken' },
  'people.linkHint': {
    en: 'Send this link to them. It works once, expires in seven days, and only for the address it was addressed to.',
    nl: 'Stuur ze deze link. Hij werkt één keer, verloopt na zeven dagen, en alleen voor het adres waaraan hij gericht is.',
  },
  'people.noEmailHint': {
    en: 'Wellformed sends no email. You get a link to pass on however you like.',
    nl: 'Wellformed verstuurt geen e-mail. Je krijgt een link die je zelf doorgeeft zoals je wilt.',
  },
  'people.createLink': { en: 'Create the link', nl: 'Link aanmaken' },

  /* Agent keys */
  'keys.title': { en: 'Agent keys', nl: 'Agentsleutels' },
  'keys.ceilingHelp.viewer': {
    en: 'Read and answer questions. Change nothing.',
    nl: 'Lezen en vragen beantwoorden. Verandert niets.',
  },
  'keys.ceilingHelp.editor': {
    en: 'Also add, edit and delete rows, and save views.',
    nl: 'Ook rijen toevoegen, bewerken en verwijderen, en weergaven opslaan.',
  },
  'keys.ceilingHelp.admin': {
    en: 'Also build tables, columns and formulas.',
    nl: 'Ook tabellen, kolommen en formules bouwen.',
  },
  'keys.intro': {
    en: 'A key lets an AI assistant read this workspace with SQL and change it through the same API the browser uses. It acts as you, with your role, and never reaches another workspace. Everything it does appears in the audit trail under your name, marked with the key’s label.',
    nl: 'Met een sleutel kan een AI-assistent deze werkruimte lezen met SQL en wijzigen via dezelfde API als de browser. Hij handelt als jij, met jouw rol, en komt nooit bij een andere werkruimte. Alles wat hij doet verschijnt in de audittrail onder jouw naam, gemarkeerd met het label van de sleutel.',
  },
  'keys.newKey': { en: 'New key', nl: 'Nieuwe sleutel' },
  'keys.noneYet': { en: 'No keys yet.', nl: 'Nog geen sleutels.' },
  'keys.copied': {
    en: 'Key copied. This is the only time it is shown.',
    nl: 'Sleutel gekopieerd. Dit is de enige keer dat hij getoond wordt.',
  },
  'keys.revokeConfirm': {
    en: (label: string) =>
      `Revoke "${label}"? Anything using it stops working immediately. What it already did stays in the audit trail.`,
    nl: (label: string) =>
      `"${label}" intrekken? Alles wat hem gebruikt stopt meteen. Wat hij al gedaan heeft, blijft in de audittrail staan.`,
  },
  'keys.label': { en: 'Label', nl: 'Label' },
  'keys.can': { en: 'Can', nl: 'Mag' },
  'keys.heldBy': { en: 'Held by', nl: 'Van' },
  'keys.lastUsed': { en: 'Last used', nl: 'Laatst gebruikt' },
  'keys.you': { en: 'you', nl: 'jij' },
  'keys.never': { en: 'never', nl: 'nooit' },
  'keys.revoke': { en: 'Revoke', nl: 'Intrekken' },
  'keys.copyNow': {
    en: 'Copy this now — it is stored hashed and cannot be shown again. If you lose it, revoke the key and make another.',
    nl: 'Kopieer dit nu — hij wordt gehasht opgeslagen en kan niet nog eens getoond worden. Raak je hem kwijt, trek de sleutel dan in en maak een nieuwe.',
  },
  'keys.newKeyAria': { en: 'The new agent key', nl: 'De nieuwe agentsleutel' },
  'keys.pointBefore': { en: 'Point an assistant at ', nl: 'Wijs een assistent naar ' },
  'keys.pointMiddle': { en: ' with the header ', nl: ' met de header ' },
  'keys.pointAfter': {
    en: '. The manifest tells it everything else.',
    nl: '. Het manifest vertelt hem de rest.',
  },
  'keys.whatFor': { en: 'What is it for', nl: 'Waar is hij voor' },
  'keys.itMay': { en: 'It may', nl: 'Hij mag' },
  'keys.ceilingHint': {
    en: (role: string) =>
      `Your role here is ${role}, so a key cannot do more than that. If your role changes later, its keys change with it.`,
    nl: (role: string) =>
      `Je rol hier is ${role}, dus een sleutel kan niet meer dan dat. Verandert je rol later, dan veranderen de sleutels mee.`,
  },
  'keys.createKey': { en: 'Create the key', nl: 'Sleutel aanmaken' },
} as const satisfies MessageCatalog;