Files
verdande/web/src/lib/colors.js
T
Kristian WindandClaude Opus 5 4d8b70918b feat(i18n): the interface speaks both languages
The account has had a `locale` since the beginning and it only chose which grammar
quick add read a line with — so picking English changed nothing anybody could see,
and the field said so honestly: "Sprog i hurtig tilføjelse". It says "Sprog" now,
because it means it.

Every component goes through `t()`. Danish is the source: a key missing from
English falls through to Danish rather than to the key, because a Danish sentence
in an English screen can be read and `settings.notifications.title` cannot.

`tag()` is the single place `Intl` is asked. Before, `'da-DK'` was written into a
dozen components, and that is the half of a translation that gets left behind — an
English interface still saying "24. aug." is exactly the shape of a job half done.
There is a smoke test that switches to English and refuses to see a Danish month
name in the calendar's heading.

Colour and theme names are keys now. `colors.js` keeps its ids untouched — they
are what the database stores, and `internal/store` reads them out of that file —
but `name` is `'color.tomato'`, resolved where it is drawn.

The Inbox keeps its name. It is a project row the server creates at signup, not a
string in the interface, and it can be renamed like any other project.

Four copies of "3 hours ago" became one, in `web/src/lib/when.js`. They had
already drifted: one said "aldrig logget ind", another "aldrig", and two stopped
at days where the others carried on to a date.

Routes stay Danish. `/indstillinger`, `/projekt`, `/uddelegeret` are bookmarks and
they are in every smoke test; translating them buys nothing and costs both.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 09:46:08 +02:00

49 lines
2.2 KiB
JavaScript

/**
* The colours a project, a group, a label or a filter can be marked with.
*
* The `color` column has been on projects since the first migration, defaulting
* to 'graphite', and nothing has ever read it. This is the list that makes it
* mean something.
*
* **One set for all five themes, deliberately.** Every other colour in this app is
* redefined per theme, because every other colour is text, a ground, or a border,
* and those have to be measured against the surface behind them. These are none of
* those: they are small solid marks sitting next to a label that carries the
* meaning. What they need is to be told apart from each other, and to be visible
* on both a near-black and a white ground — which mid-tone, medium-saturation
* colours are, and which is why they are all in that band.
*
* Defining them once is also what keeps them out of the trap the themes are in:
* a colour added to four theme blocks and forgotten in the fifth looks finished
* and falls back silently. There is no fifth block to forget.
*
* The ids are what the database stores, so they are not to be renamed. `app.css`
* carries a `--color-<id>` token for each, and a Go test reads this file to check
* the server's list of accepted names has not drifted from it.
*/
// `name` is a key rather than a word: the picker calls `t()` on it. The ids stay
// exactly as they are — they are what the database stores, and `internal/store`
// has a test that reads them out of this file.
export const COLORS = [
{ id: 'graphite', name: 'color.graphite' },
{ id: 'tomato', name: 'color.tomato' },
{ id: 'amber', name: 'color.amber' },
{ id: 'lime', name: 'color.lime' },
{ id: 'green', name: 'color.green' },
{ id: 'teal', name: 'color.teal' },
{ id: 'blue', name: 'color.blue' },
{ id: 'indigo', name: 'color.indigo' },
{ id: 'violet', name: 'color.violet' },
{ id: 'magenta', name: 'color.magenta' }
];
/** The CSS variable a colour id paints with, falling back to the default. */
export function colorVar(id) {
return COLORS.some((c) => c.id === id) ? `var(--color-${id})` : 'var(--color-graphite)';
}
/** The Danish name, for the swatch's label. */
export function colorName(id) {
return COLORS.find((c) => c.id === id)?.name ?? COLORS[0].name;
}