Spreadsheet-UX op een echte relationele engine
Deze repository wordt als momentopname gepubliceerd: een clone bevat de volledige inhoud, maar geen commitgeschiedenis.
import { formatCount, type Locale } from '@wellformed/shared';
import type { MessageCatalog } from './entry';
/** The grid and the strips around it: cells, menus, filters, views, the SQL echo. */
export const grid = {
/* the grid's own states */
'grid.noTable': { en: 'No table selected.', nl: 'Geen tabel geselecteerd.' },
'grid.rowsFailed': {
en: 'Could not load rows.',
nl: 'De rijen konden niet worden geladen.',
},
'grid.loadingTable': {
en: (label: string) => `Loading ${label}…`,
nl: (label: string) => `${label} wordt geladen…`,
},
'grid.loadingMore': { en: 'Loading more…', nl: 'Meer laden…' },
'grid.noRowsMatch': {
en: 'No rows match these filters.',
nl: 'Geen rijen voldoen aan deze filters.',
},
'grid.noRowsYet': {
en: (label: string) => `No rows in ${label} yet.`,
nl: (label: string) => `Nog geen rijen in ${label}.`,
},
'grid.gridLabel': {
en: (label: string) => `${label} grid`,
nl: (label: string) => `Raster van ${label}`,
},
/* rows: adding, composing, deleting */
'grid.newRow': { en: 'New row', nl: 'Nieuwe rij' },
'grid.demoReadOnly': {
en: 'This is the published demo, read-only. Make your own workspace to edit — the button is top right.',
nl: 'Dit is de gepubliceerde demo, alleen-lezen. Maak er zelf een om te bewerken — de knop staat rechtsboven.',
},
'grid.viewerReadOnly': {
en: 'You are a viewer in this workspace, so the grid is read-only.',
nl: 'Je bent kijker in deze werkruimte, dus het raster is alleen-lezen.',
},
'grid.draftFillIn': {
en: (cols: string) => `Fill in ${cols} to create the row`,
nl: (cols: string) => `Vul ${cols} in om de rij aan te maken`,
},
'grid.draftDiscard': { en: 'Esc to discard', nl: 'Esc om te verwerpen' },
'grid.notSavedYet': { en: 'Not saved yet', nl: 'Nog niet opgeslagen' },
'grid.deletedRow': {
en: (label: string) => `Deleted ${label}.`,
nl: (label: string) => `${label} is verwijderd.`,
},
'grid.ruleFired': {
en: (workflow: string) => `Rule fired — ${workflow}`,
nl: (workflow: string) => `Regel uitgevoerd — ${workflow}`,
},
/* what the undo history calls each change */
'grid.undoCellEdit': {
en: (col: string, row: string) => `${col} on ${row}`,
nl: (col: string, row: string) => `${col} van ${row}`,
},
'grid.undoNewRow': {
en: (table: string) => `new row in ${table}`,
nl: (table: string) => `nieuwe rij in ${table}`,
},
'grid.undoDeleteRow': {
en: (label: string) => `delete ${label}`,
nl: (label: string) => `${label} verwijderen`,
},
'grid.undoPaste': {
en: (row: string) => `paste into ${row}`,
nl: (row: string) => `plakken in ${row}`,
},
/* clipboard */
'grid.copied': { en: 'Copied.', nl: 'Gekopieerd.' },
'grid.copiedCells': {
en: (n: number, locale: Locale) => `Copied ${formatCount(n, locale)} cells.`,
nl: (n: number, locale: Locale) => `${formatCount(n, locale)} cellen gekopieerd.`,
},
/* hiding columns from the grid */
'grid.hideColumn': { en: 'Hide column', nl: 'Kolom verbergen' },
'grid.showHiddenColumns': {
en: (n: number) => `Show hidden columns (${n})`,
nl: (n: number) => `Verborgen kolommen tonen (${n})`,
},
/* the block selection */
'grid.selectionMenu': { en: 'Selection', nl: 'Selectie' },
'grid.copySelection': { en: 'Copy selection', nl: 'Selectie kopiëren' },
'grid.clearSelection': { en: 'Clear selection', nl: 'Selectie opheffen' },
'grid.clipboardRefused': {
en: 'The browser would not give Wellformed clipboard access.',
nl: 'De browser geeft Wellformed geen toegang tot het klembord.',
},
'grid.pasteTooBig': {
en: (n: number, max: number, locale: Locale) =>
`That is ${formatCount(n, locale)} cells; paste at most ${formatCount(max, locale)} at a time.`,
nl: (n: number, max: number, locale: Locale) =>
`Dat zijn ${formatCount(n, locale)} cellen; plak er hoogstens ${formatCount(max, locale)} tegelijk.`,
},
'grid.pasted': {
en: (n: number, locale: Locale) =>
`Pasted into ${formatCount(n, locale)} row${n === 1 ? '' : 's'}.`,
nl: (n: number, locale: Locale) =>
`Geplakt in ${formatCount(n, locale)} rij${n === 1 ? '' : 'en'}.`,
},
'grid.pastedSkipped': {
en: (n: number, locale: Locale) =>
`${formatCount(n, locale)} computed cell${n === 1 ? '' : 's'} skipped.`,
nl: (n: number, locale: Locale) =>
`${formatCount(n, locale)} berekende cel${n === 1 ? '' : 'len'} overgeslagen.`,
},
/* column headers */
'grid.colRequired': {
en: (name: string) => `${name} is required`,
nl: (name: string) => `${name} is verplicht`,
},
'grid.colUnique': {
en: (name: string) => `${name} must be unique`,
nl: (name: string) => `${name} moet uniek zijn`,
},
'grid.resizeCol': {
en: (name: string) => `Resize ${name}`,
nl: (name: string) => `Breedte van ${name} aanpassen`,
},
/* the header, summary and row menus */
'grid.columnMenu': {
en: (name: string) => `${name} column`,
nl: (name: string) => `Kolom ${name}`,
},
'grid.rowActions': { en: 'Row actions', nl: 'Rijacties' },
'grid.sortAsc': { en: 'Sort ascending', nl: 'Oplopend sorteren' },
'grid.sortDesc': { en: 'Sort descending', nl: 'Aflopend sorteren' },
'grid.clearSort': { en: 'Clear sort', nl: 'Sortering wissen' },
'grid.filterByColumn': { en: 'Filter by this column', nl: 'Filteren op deze kolom' },
'grid.resetWidth': { en: 'Reset width', nl: 'Breedte herstellen' },
'grid.useAsRowLabel': { en: 'Use as row label', nl: 'Als rijlabel gebruiken' },
'grid.editColumn': { en: 'Edit column…', nl: 'Kolom bewerken…' },
'grid.tightenColumn': { en: 'Tighten column…', nl: 'Kolom aanscherpen…' },
'grid.addColumn': { en: 'Add column…', nl: 'Kolom toevoegen…' },
'grid.deleteColumn': { en: 'Delete column', nl: 'Kolom verwijderen' },
'grid.showHistory': {
en: 'Show this row’s history',
nl: 'Geschiedenis van deze rij tonen',
},
'grid.copyRowId': { en: 'Copy row id', nl: 'Rij-id kopiëren' },
'grid.deleteRow': { en: 'Delete row', nl: 'Rij verwijderen' },
/* the aggregate row and its functions */
'grid.rowCountTitle': {
en: (n: number, locale: Locale) => `${formatCount(n, locale)} row${n === 1 ? '' : 's'}`,
nl: (n: number, locale: Locale) => `${formatCount(n, locale)} rij${n === 1 ? '' : 'en'}`,
},
'grid.summarise': {
en: (name: string) => `Summarise ${name}`,
nl: (name: string) => `${name} samenvatten`,
},
'grid.summariseThis': { en: 'Summarise this column', nl: 'Deze kolom samenvatten' },
'grid.summaryOf': {
en: (fn: string, col: string, text: string) => `${fn} of ${col}: ${text}`,
nl: (fn: string, col: string, text: string) => `${fn} van ${col}: ${text}`,
},
'grid.noSummary': { en: 'No summary', nl: 'Geen samenvatting' },
'grid.agg.sum': { en: 'Sum', nl: 'Som' },
'grid.agg.avg': { en: 'Average', nl: 'Gemiddelde' },
'grid.agg.min': { en: 'Min', nl: 'Min' },
'grid.agg.max': { en: 'Max', nl: 'Max' },
'grid.agg.filled': { en: 'Filled', nl: 'Gevuld' },
'grid.agg.empty': { en: 'Empty', nl: 'Leeg' },
'grid.agg.unique': { en: 'Unique', nl: 'Uniek' },
'grid.agg.checked': { en: 'Checked', nl: 'Aangevinkt' },
'grid.agg.unchecked': { en: 'Unchecked', nl: 'Niet aangevinkt' },
'grid.agg.earliest': { en: 'Earliest', nl: 'Vroegste' },
'grid.agg.latest': { en: 'Latest', nl: 'Laatste' },
/* cells */
'grid.cellError': { en: '#ERROR', nl: '#FOUT' },
'grid.openLink': {
en: (label: string) => `Open ${label}`,
nl: (label: string) => `${label} openen`,
},
/* the link picker */
'grid.searchPlaceholder': { en: 'Search…', nl: 'Zoeken…' },
'grid.linkRows': {
en: (col: string) => `${col} rows`,
nl: (col: string) => `Rijen voor ${col}`,
},
'grid.noLinkMatches': { en: 'No rows match.', nl: 'Geen rijen gevonden.' },
'grid.linkCapped': {
en: (n: number, locale: Locale) =>
`Searching the first ${formatCount(n, locale)} rows only.`,
nl: (n: number, locale: Locale) =>
`Er wordt alleen in de eerste ${formatCount(n, locale)} rijen gezocht.`,
},
/* the record panel behind a link */
'grid.openInTable': {
en: (label: string) => `Open in ${label}`,
nl: (label: string) => `Openen in ${label}`,
},
'grid.linkRowNotLoaded': {
en: (n: number, label: string, locale: Locale) =>
`This row is not among the first ${formatCount(n, locale)} of ${label}, so there is nothing loaded to show. Open the table to find it.`,
nl: (n: number, label: string, locale: Locale) =>
`Deze rij zit niet bij de eerste ${formatCount(n, locale)} van ${label}, dus er is niets geladen om te tonen. Open de tabel om hem te vinden.`,
},
/* the formula bar */
'grid.noSelection': { en: 'no selection', nl: 'geen selectie' },
'grid.cellValue': { en: 'Cell value', nl: 'Celwaarde' },
'grid.typeColumn': {
en: (type: string) => `${type} column`,
nl: (type: string) => `${type}-kolom`,
},
'grid.evaluatedInSql': {
en: (type: string) => `evaluated in SQL · ${type}`,
nl: (type: string) => `berekend in SQL · ${type}`,
},
'grid.foreignKey': {
en: (target: string) => `foreign key → ${target}`,
nl: (target: string) => `koppeling → ${target}`,
},
'grid.anotherTable': { en: 'another table', nl: 'een andere tabel' },
/* the SQL bar: the query itself stays SQL; only the frame speaks */
'grid.sqlRowCount': {
en: (n: number, locale: Locale) => `${formatCount(n, locale)} ROW${n === 1 ? '' : 'S'}`,
nl: (n: number, locale: Locale) => `${formatCount(n, locale)} RIJ${n === 1 ? '' : 'EN'}`,
},
'grid.viewSql': { en: 'view SQL ▸', nl: 'SQL bekijken ▸' },
'grid.hideSql': { en: 'hide SQL ▾', nl: 'SQL verbergen ▾' },
'grid.copySql': { en: 'COPY', nl: 'KOPIËREN' },
'grid.sqlCopied': { en: 'SQL copied.', nl: 'SQL gekopieerd.' },
'grid.sqlForView': { en: 'SQL for the current view', nl: 'SQL voor de huidige weergave' },
'grid.sqlForSummary': { en: 'SQL for the aggregate row', nl: 'SQL voor de samenvattingsrij' },
/* the view bar: filters and saved views */
'grid.addFilterOption': { en: '+ filter…', nl: '+ filter…' },
'grid.filterColumn': { en: 'Filter column', nl: 'Filterkolom' },
'grid.filterOperator': { en: 'Filter operator', nl: 'Filteroperator' },
'grid.filterValue': { en: 'Filter value', nl: 'Filterwaarde' },
'grid.valuePlaceholder': { en: 'value', nl: 'waarde' },
'grid.applyFilter': { en: 'Apply', nl: 'Toepassen' },
'grid.removeFilter': {
en: (filter: string) => `Remove filter ${filter}`,
nl: (filter: string) => `Filter ${filter} verwijderen`,
},
'grid.op.contains': { en: 'contains', nl: 'bevat' },
'grid.op.isEmpty': { en: 'is empty', nl: 'is leeg' },
'grid.op.isNotEmpty': { en: 'is not empty', nl: 'is niet leeg' },
'grid.nameThisView': { en: 'Name this view', nl: 'Geef deze weergave een naam' },
'grid.newView': { en: 'New view', nl: 'Nieuwe weergave' },
'grid.saveAsView': { en: 'Save as view', nl: 'Opslaan als weergave' },
'grid.updateView': {
en: (name: string) => `Update “${name}”`,
nl: (name: string) => `“${name}” bijwerken`,
},
'grid.savedView': {
en: (name: string) => `Saved view “${name}”.`,
nl: (name: string) => `Weergave “${name}” opgeslagen.`,
},
'grid.updatedView': {
en: (name: string) => `Updated “${name}”.`,
nl: (name: string) => `“${name}” bijgewerkt.`,
},
'grid.deleteView': { en: 'Delete view', nl: 'Weergave verwijderen' },
'grid.deleteViewConfirm': {
en: (name: string) => `Delete the view “${name}”?`,
nl: (name: string) => `De weergave “${name}” verwijderen?`,
},
} as const satisfies MessageCatalog;