import { formatCount, type Locale } from '@wellformed/shared'; import type { MessageCatalog } from './entry'; /** * The marketing page's fixed chrome. The four selling points in the middle are * not here on purpose: they come from the voice pool, measured copy with fixed * ids — see `shared/voice.ts`. */ export const marketing = { /* What search results and link previews show. The title repeats the headline because the headline is the argument; the description compresses the lede to what fits a result snippet. */ 'marketing.metaTitle': { en: 'Wellformed — the spreadsheet that can’t quietly go wrong', nl: 'Wellformed — de spreadsheet die niet stilletjes fout kan gaan', }, 'marketing.metaDescription': { en: 'A spreadsheet with a real database underneath: every column has a type, every link points ' + 'at a row that exists, and mistakes are refused the moment somebody makes them.', nl: 'Een spreadsheet met een echte database eronder: elke kolom heeft een type, elke koppeling ' + 'wijst naar een rij die echt bestaat, en fouten worden geweigerd op het moment dat iemand ' + 'ze maakt.', }, 'marketing.pricing': { en: 'Pricing', nl: 'Prijzen' }, 'marketing.yourWorkspaces': { en: 'Your workspaces', nl: 'Je werkruimtes' }, 'marketing.startFree': { en: 'Start free', nl: 'Gratis beginnen' }, 'marketing.strapline': { en: 'A spreadsheet with a database underneath', nl: 'Een spreadsheet met een database eronder', }, 'marketing.headline': { en: 'The spreadsheet that can’t quietly go wrong', nl: 'De spreadsheet die niet stilletjes fout kan gaan', }, 'marketing.lede': { en: 'You still click a cell, type, and press Enter. What is different sits underneath: every column has a type, every link points at a row that really exists, and required means required. So the mistakes that used to sit in the file for months — a word where a price goes, an order pointing at a customer who was deleted, a blank nobody noticed — are refused at the moment somebody makes them.', nl: 'Je klikt nog steeds op een cel, typt, en drukt op Enter. Het verschil zit eronder: elke kolom heeft een type, elke koppeling wijst naar een rij die echt bestaat, en verplicht betekent verplicht. Dus de fouten die vroeger maandenlang in het bestand bleven zitten — een woord waar een prijs hoort, een order die wijst naar een verwijderde klant, een leeg vakje dat niemand opviel — worden geweigerd op het moment dat iemand ze maakt.', }, 'marketing.moveOver': { en: 'Move a spreadsheet over', nl: 'Zet een spreadsheet over' }, 'marketing.openDemo': { en: 'Open the demo — no account', nl: 'Open de demo — zonder account' }, 'marketing.freeToStart': { en: (tables: string, rows: string) => `Free to start, no card — ${tables} and ${rows}, enough to move a real spreadsheet over and see whether it holds.`, nl: (tables: string, rows: string) => `Gratis om te beginnen, geen creditcard — ${tables} en ${rows}, genoeg om een echte spreadsheet over te zetten en te zien of het standhoudt.`, }, 'marketing.inviteOnly': { en: 'This installation is invitation-only. Ask someone here to invite you.', nl: 'Deze installatie is alleen op uitnodiging. Vraag iemand hier om je uit te nodigen.', }, 'marketing.proofLabel': { en: 'A workspace, a few weeks in', nl: 'Een werkruimte, een paar weken verder', }, 'marketing.proofAlt': { en: 'An orders table in Wellformed: each row links to a customer and a product, a Total column adds itself up from the linked price — the strip above the grid shows the formula behind the selected total — saved views and a workflow rule sit in the sidebar, and the strip along the bottom shows the SQL statement behind the screen.', nl: 'Een ordertabel in Wellformed: elke rij is gekoppeld aan een klant en een product, een totaalkolom telt zichzelf op uit de gekoppelde prijs — de strook boven het raster toont de formule achter het geselecteerde totaal — opgeslagen weergaven en een workflowregel staan in de zijbalk, en de strook onderaan toont het SQL-statement achter het scherm.', }, 'marketing.proofHint': { en: 'Orders linked to customers and products, a total that works itself out, and the saved views down the side. The dark strip is the part nobody else shows you: the exact statement behind what you are looking at. You never have to read it — it is there so no number on this screen has to be taken on trust.', nl: 'Orders gekoppeld aan klanten en producten, een totaal dat zichzelf uitrekent, en de opgeslagen weergaven aan de zijkant. De donkere strook is het deel dat niemand anders je laat zien: het exacte statement achter wat je bekijkt. Je hoeft het nooit te lezen — het staat er zodat je geen enkel getal op dit scherm op gezag hoeft aan te nemen.', }, 'marketing.pricingTitle': { en: 'Two prices, and that is the whole price list.', nl: 'Twee prijzen, en dat is de hele prijslijst.', }, 'marketing.pricingHint': { en: 'Per workspace, not per person. Add everyone you work with on either tier.', nl: 'Per werkruimte, niet per persoon. Voeg op beide niveaus iedereen toe met wie je werkt.', }, 'marketing.perMonth': { en: '/month', nl: '/maand' }, 'marketing.limitRows': { en: (limit: number | null, locale: Locale) => limit === null ? 'unlimited rows' : `${formatCount(limit, locale)} rows`, nl: (limit: number | null, locale: Locale) => limit === null ? 'onbeperkt aantal rijen' : `${formatCount(limit, locale)} rijen`, }, 'marketing.limitTables': { en: (limit: number | null, locale: Locale) => limit === null ? 'unlimited tables' : `${formatCount(limit, locale)} tables`, nl: (limit: number | null, locale: Locale) => limit === null ? 'onbeperkt aantal tabellen' : `${formatCount(limit, locale)} tabellen`, }, 'marketing.startFreeUpgrade': { en: 'Start free, upgrade later', nl: 'Gratis beginnen, later upgraden', }, 'marketing.vatHint': { en: 'Prices exclude VAT. A workspace that reaches its limit stops taking new rows and new tables — nothing is locked, nothing is deleted, and you can still export all of it.', nl: 'Prijzen zijn exclusief btw. Een werkruimte die zijn limiet bereikt neemt geen nieuwe rijen en tabellen meer aan — niets gaat op slot, niets wordt verwijderd, en je kunt nog steeds alles exporteren.', }, 'marketing.closer': { en: 'Move one real table over and see what it refuses. That takes about ten minutes, and it settles the question better than any page can.', nl: 'Zet één echte tabel over en kijk wat hij weigert. Dat kost een minuut of tien, en het beantwoordt de vraag beter dan welke pagina ook.', }, 'marketing.demo': { en: 'Demo', nl: 'Demo' }, /* * The pricing-card copy. The *numbers* stay in shared/plans.ts so the page * and the server's enforcement cannot drift apart; the words about them live * here with every other word the client speaks. The plan names — Free, Team — * are product names and stay as they are. */ 'marketing.plan.free.blurb': { en: 'Enough to move a real spreadsheet over and see whether it holds.', nl: 'Genoeg om een echte spreadsheet over te zetten en te zien of het standhoudt.', }, 'marketing.plan.free.include1': { en: 'Everything in the engine: links, formulas, rollups, views', nl: 'Alles in de engine: koppelingen, formules, rollups, weergaven', }, 'marketing.plan.free.include2': { en: 'Unlimited people, any mix of admins, editors and viewers', nl: 'Onbeperkt mensen, elke mix van beheerders, bewerkers en kijkers', }, 'marketing.plan.free.include3': { en: 'The full audit trail', nl: 'De volledige audittrail', }, 'marketing.plan.free.include4': { en: 'Export the whole workspace as a SQLite file, whenever you like', nl: 'Exporteer de hele werkruimte als SQLite-bestand, wanneer je maar wilt', }, 'marketing.plan.team.blurb': { en: 'One flat price per workspace. Add everyone you work with.', nl: 'Eén vaste prijs per werkruimte. Voeg iedereen toe met wie je werkt.', }, 'marketing.plan.team.include1': { en: 'Everything in Free, without the ceiling', nl: 'Alles van Free, zonder het plafond', }, 'marketing.plan.team.include2': { en: 'As many tables as the work needs', nl: 'Zoveel tabellen als het werk nodig heeft', }, 'marketing.plan.team.include3': { en: (rows: number, locale: Locale) => `${formatCount(rows, locale)} rows per workspace`, nl: (rows: number, locale: Locale) => `${formatCount(rows, locale)} rijen per werkruimte`, }, 'marketing.plan.team.include4': { en: 'Still unlimited people — there is no per-seat price to plan around', nl: 'Nog steeds onbeperkt mensen — er is geen prijs per gebruiker om rekening mee te houden', }, } as const satisfies MessageCatalog;