@tea-ui/ux-standards 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +24 -0
- package/dist/destructive.d.ts +58 -0
- package/dist/destructive.js +50 -0
- package/dist/destructive.js.map +1 -0
- package/dist/error-anatomy.d.ts +82 -0
- package/dist/error-anatomy.js +68 -0
- package/dist/error-anatomy.js.map +1 -0
- package/dist/feedback.d.ts +65 -0
- package/dist/feedback.js +159 -0
- package/dist/feedback.js.map +1 -0
- package/dist/forms.d.ts +86 -0
- package/dist/forms.js +79 -0
- package/dist/forms.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +113 -0
- package/dist/index.js.map +1 -0
- package/dist/motion.d.ts +126 -0
- package/dist/motion.js +67 -0
- package/dist/motion.js.map +1 -0
- package/dist/navigation.d.ts +42 -0
- package/dist/navigation.js +73 -0
- package/dist/navigation.js.map +1 -0
- package/dist/status.d.ts +50 -0
- package/dist/status.js +303 -0
- package/dist/status.js.map +1 -0
- package/dist/terminology.d.ts +141 -0
- package/dist/terminology.js +161 -0
- package/dist/terminology.js.map +1 -0
- package/package.json +52 -0
package/dist/status.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
function domain(entries) {
|
|
2
|
+
return entries;
|
|
3
|
+
}
|
|
4
|
+
const HEALTH = domain({
|
|
5
|
+
online: {
|
|
6
|
+
label: "Online",
|
|
7
|
+
tone: "positive",
|
|
8
|
+
description: "Der Dienst antwortet normal und erf\xFCllt seine Aufgabe."
|
|
9
|
+
},
|
|
10
|
+
degraded: {
|
|
11
|
+
label: "Eingeschr\xE4nkt",
|
|
12
|
+
tone: "caution",
|
|
13
|
+
description: "Der Dienst antwortet, aber einzelne Funktionen sind nicht verf\xFCgbar."
|
|
14
|
+
},
|
|
15
|
+
offline: {
|
|
16
|
+
label: "Offline",
|
|
17
|
+
tone: "critical",
|
|
18
|
+
description: "Der Dienst ist nicht erreichbar."
|
|
19
|
+
},
|
|
20
|
+
unknown: {
|
|
21
|
+
label: "Unbekannt",
|
|
22
|
+
tone: "neutral",
|
|
23
|
+
description: "Es liegt keine aktuelle Messung vor."
|
|
24
|
+
},
|
|
25
|
+
maintenance: {
|
|
26
|
+
label: "Wartung",
|
|
27
|
+
tone: "info",
|
|
28
|
+
description: "Der Dienst wird geplant bearbeitet und ist m\xF6glicherweise nicht verf\xFCgbar."
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const RESOURCE = domain({
|
|
32
|
+
normal: {
|
|
33
|
+
label: "Normal",
|
|
34
|
+
tone: "positive",
|
|
35
|
+
description: "Die Auslastung liegt im \xFCblichen Bereich."
|
|
36
|
+
},
|
|
37
|
+
elevated: {
|
|
38
|
+
label: "Erh\xF6ht",
|
|
39
|
+
tone: "caution",
|
|
40
|
+
description: "Die Auslastung n\xE4hert sich dem Grenzwert."
|
|
41
|
+
},
|
|
42
|
+
high: {
|
|
43
|
+
label: "Hoch",
|
|
44
|
+
tone: "caution",
|
|
45
|
+
description: "Die Auslastung liegt \xFCber dem Zielwert und sollte beobachtet werden."
|
|
46
|
+
},
|
|
47
|
+
critical: {
|
|
48
|
+
label: "Kritisch",
|
|
49
|
+
tone: "critical",
|
|
50
|
+
description: "Die Auslastung hat den Grenzwert \xFCberschritten. Handeln ist erforderlich."
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const BACKUP = domain({
|
|
54
|
+
succeeded: {
|
|
55
|
+
label: "Erfolgreich",
|
|
56
|
+
tone: "positive",
|
|
57
|
+
description: "Die Sicherung wurde vollst\xE4ndig geschrieben und gepr\xFCft."
|
|
58
|
+
},
|
|
59
|
+
running: {
|
|
60
|
+
label: "L\xE4uft",
|
|
61
|
+
tone: "info",
|
|
62
|
+
description: "Die Sicherung wird gerade geschrieben."
|
|
63
|
+
},
|
|
64
|
+
pending: {
|
|
65
|
+
label: "Ausstehend",
|
|
66
|
+
tone: "neutral",
|
|
67
|
+
description: "Die Sicherung ist geplant, aber noch nicht gestartet."
|
|
68
|
+
},
|
|
69
|
+
failed: {
|
|
70
|
+
label: "Fehlgeschlagen",
|
|
71
|
+
tone: "critical",
|
|
72
|
+
description: "Die Sicherung wurde abgebrochen und ist nicht verwendbar."
|
|
73
|
+
},
|
|
74
|
+
expired: {
|
|
75
|
+
label: "Abgelaufen",
|
|
76
|
+
tone: "caution",
|
|
77
|
+
description: "Die Sicherung ist \xE4lter als die Aufbewahrungsfrist."
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
const CERTIFICATE = domain({
|
|
81
|
+
valid: {
|
|
82
|
+
label: "G\xFCltig",
|
|
83
|
+
tone: "positive",
|
|
84
|
+
description: "Das Zertifikat ist g\xFCltig und wird automatisch erneuert."
|
|
85
|
+
},
|
|
86
|
+
expiring: {
|
|
87
|
+
label: "L\xE4uft ab",
|
|
88
|
+
tone: "caution",
|
|
89
|
+
description: "Das Zertifikat l\xE4uft in K\xFCrze ab und sollte erneuert werden."
|
|
90
|
+
},
|
|
91
|
+
expired: {
|
|
92
|
+
label: "Abgelaufen",
|
|
93
|
+
tone: "critical",
|
|
94
|
+
description: "Das Zertifikat ist abgelaufen. Die Verbindung ist nicht mehr vertrauensw\xFCrdig."
|
|
95
|
+
},
|
|
96
|
+
invalid: {
|
|
97
|
+
label: "Ung\xFCltig",
|
|
98
|
+
tone: "critical",
|
|
99
|
+
description: "Das Zertifikat konnte nicht gepr\xFCft werden."
|
|
100
|
+
},
|
|
101
|
+
unknown: {
|
|
102
|
+
label: "Unbekannt",
|
|
103
|
+
tone: "neutral",
|
|
104
|
+
description: "Es liegt keine aktuelle Pr\xFCfung vor."
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const CONTAINER = domain({
|
|
108
|
+
running: {
|
|
109
|
+
label: "L\xE4uft",
|
|
110
|
+
tone: "positive",
|
|
111
|
+
description: "Der Container ist gestartet und wird ausgef\xFChrt."
|
|
112
|
+
},
|
|
113
|
+
created: {
|
|
114
|
+
label: "Erstellt",
|
|
115
|
+
tone: "neutral",
|
|
116
|
+
description: "Der Container ist angelegt, aber nicht gestartet."
|
|
117
|
+
},
|
|
118
|
+
paused: {
|
|
119
|
+
label: "Pausiert",
|
|
120
|
+
tone: "info",
|
|
121
|
+
description: "Der Container ist angehalten und speichert seinen Zustand."
|
|
122
|
+
},
|
|
123
|
+
restarting: {
|
|
124
|
+
label: "Startet neu",
|
|
125
|
+
tone: "info",
|
|
126
|
+
description: "Der Container wird gerade neu gestartet."
|
|
127
|
+
},
|
|
128
|
+
stopped: {
|
|
129
|
+
label: "Gestoppt",
|
|
130
|
+
tone: "neutral",
|
|
131
|
+
description: "Der Container ist gestoppt."
|
|
132
|
+
},
|
|
133
|
+
error: {
|
|
134
|
+
label: "Fehler",
|
|
135
|
+
tone: "critical",
|
|
136
|
+
description: "Der Container l\xE4uft nicht, weil ein Fehler aufgetreten ist."
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
const WEBSITE = domain({
|
|
140
|
+
online: {
|
|
141
|
+
label: "Online",
|
|
142
|
+
tone: "positive",
|
|
143
|
+
description: "Die Website ist erreichbar und wird ausgeliefert."
|
|
144
|
+
},
|
|
145
|
+
deploying: {
|
|
146
|
+
label: "Wird ausgerollt",
|
|
147
|
+
tone: "info",
|
|
148
|
+
description: "Eine neue Version wird gerade ver\xF6ffentlicht."
|
|
149
|
+
},
|
|
150
|
+
degraded: {
|
|
151
|
+
label: "Eingeschr\xE4nkt",
|
|
152
|
+
tone: "caution",
|
|
153
|
+
description: "Die Website ist erreichbar, hat aber Performance- oder Zertifikatsprobleme."
|
|
154
|
+
},
|
|
155
|
+
offline: {
|
|
156
|
+
label: "Offline",
|
|
157
|
+
tone: "critical",
|
|
158
|
+
description: "Die Website ist nicht erreichbar."
|
|
159
|
+
},
|
|
160
|
+
error: {
|
|
161
|
+
label: "Fehler",
|
|
162
|
+
tone: "critical",
|
|
163
|
+
description: "Beim Ausliefern der Website ist ein Fehler aufgetreten."
|
|
164
|
+
},
|
|
165
|
+
unknown: {
|
|
166
|
+
label: "Unbekannt",
|
|
167
|
+
tone: "neutral",
|
|
168
|
+
description: "Es liegt keine aktuelle Pr\xFCfung vor."
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
const DEPENDENCY = domain({
|
|
172
|
+
ok: { label: "In Ordnung", tone: "positive", description: "Die Abh\xE4ngigkeit ist vorhanden und aktuell." },
|
|
173
|
+
warning: {
|
|
174
|
+
label: "Warnung",
|
|
175
|
+
tone: "caution",
|
|
176
|
+
description: "Die Abh\xE4ngigkeit ist veraltet oder auff\xE4llig."
|
|
177
|
+
},
|
|
178
|
+
missing: {
|
|
179
|
+
label: "Fehlt",
|
|
180
|
+
tone: "critical",
|
|
181
|
+
description: "Die Abh\xE4ngigkeit wird ben\xF6tigt, ist aber nicht installiert."
|
|
182
|
+
},
|
|
183
|
+
error: {
|
|
184
|
+
label: "Fehler",
|
|
185
|
+
tone: "critical",
|
|
186
|
+
description: "Die Abh\xE4ngigkeit konnte nicht gepr\xFCft werden."
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
const SECURITY = domain({
|
|
190
|
+
ok: { label: "In Ordnung", tone: "positive", description: "Es wurde kein Problem gefunden." },
|
|
191
|
+
warning: {
|
|
192
|
+
label: "Warnung",
|
|
193
|
+
tone: "caution",
|
|
194
|
+
description: "Es wurde ein Problem mit geringer Risiko gefunden."
|
|
195
|
+
},
|
|
196
|
+
critical: {
|
|
197
|
+
label: "Kritisch",
|
|
198
|
+
tone: "critical",
|
|
199
|
+
description: "Es wurde ein Problem mit hohem Risiko gefunden, das sofort behoben werden sollte."
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
const CRM = domain({
|
|
203
|
+
unprocessed: {
|
|
204
|
+
label: "Unbearbeitet",
|
|
205
|
+
tone: "neutral",
|
|
206
|
+
description: "Der Eintrag wurde erfasst, aber noch nicht bewertet."
|
|
207
|
+
},
|
|
208
|
+
no_website: {
|
|
209
|
+
label: "Ohne Website",
|
|
210
|
+
tone: "neutral",
|
|
211
|
+
description: "F\xFCr den Eintrag wurde keine Website gefunden."
|
|
212
|
+
},
|
|
213
|
+
opportunity: {
|
|
214
|
+
label: "Interesse",
|
|
215
|
+
tone: "info",
|
|
216
|
+
description: "Es gibt einen Hinweis auf Interesse, aber noch keinen Kontakt."
|
|
217
|
+
},
|
|
218
|
+
contacted: {
|
|
219
|
+
label: "Kontaktiert",
|
|
220
|
+
tone: "info",
|
|
221
|
+
description: "Erster Kontakt hergestellt, Antwort steht aus."
|
|
222
|
+
},
|
|
223
|
+
conversation: {
|
|
224
|
+
label: "Im Gespr\xE4ch",
|
|
225
|
+
tone: "info",
|
|
226
|
+
description: "Es findet ein aktiver Austausch \xFCber das Angebot statt."
|
|
227
|
+
},
|
|
228
|
+
offer: {
|
|
229
|
+
label: "Angebot",
|
|
230
|
+
tone: "caution",
|
|
231
|
+
description: "Ein Angebot wurde erstellt und wartet auf eine Entscheidung."
|
|
232
|
+
},
|
|
233
|
+
customer: {
|
|
234
|
+
label: "Kunde",
|
|
235
|
+
tone: "positive",
|
|
236
|
+
description: "Der Einstieg ist abgeschlossen."
|
|
237
|
+
},
|
|
238
|
+
archived: {
|
|
239
|
+
label: "Archiviert",
|
|
240
|
+
tone: "neutral",
|
|
241
|
+
description: "Der Eintrag ist abgeschlossen und wird nicht weiter bearbeitet."
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
const PROJECT = domain({
|
|
245
|
+
planning: {
|
|
246
|
+
label: "In Planung",
|
|
247
|
+
tone: "neutral",
|
|
248
|
+
description: "Das Projekt ist eingeplant, aber noch nicht gestartet."
|
|
249
|
+
},
|
|
250
|
+
active: {
|
|
251
|
+
label: "In Arbeit",
|
|
252
|
+
tone: "info",
|
|
253
|
+
description: "Das Projekt wird gerade umgesetzt."
|
|
254
|
+
},
|
|
255
|
+
on_hold: {
|
|
256
|
+
label: "Pausiert",
|
|
257
|
+
tone: "caution",
|
|
258
|
+
description: "Das Projekt ruht und wartet auf eine Entscheidung oder Zuarbeit."
|
|
259
|
+
},
|
|
260
|
+
review: {
|
|
261
|
+
label: "In Pr\xFCfung",
|
|
262
|
+
tone: "caution",
|
|
263
|
+
description: "Das Ergebnis wird gepr\xFCft und abgenommen."
|
|
264
|
+
},
|
|
265
|
+
delivered: {
|
|
266
|
+
label: "Abgeschlossen",
|
|
267
|
+
tone: "positive",
|
|
268
|
+
description: "Das Projekt ist abgenommen."
|
|
269
|
+
},
|
|
270
|
+
cancelled: {
|
|
271
|
+
label: "Abgebrochen",
|
|
272
|
+
tone: "neutral",
|
|
273
|
+
description: "Das Projekt wurde abgebrochen und wird nicht weiterverfolgt."
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
const STATUS = {
|
|
277
|
+
health: HEALTH,
|
|
278
|
+
resource: RESOURCE,
|
|
279
|
+
backup: BACKUP,
|
|
280
|
+
certificate: CERTIFICATE,
|
|
281
|
+
container: CONTAINER,
|
|
282
|
+
website: WEBSITE,
|
|
283
|
+
dependency: DEPENDENCY,
|
|
284
|
+
security: SECURITY,
|
|
285
|
+
crm: CRM,
|
|
286
|
+
project: PROJECT
|
|
287
|
+
};
|
|
288
|
+
function statusMeta(domain2, key) {
|
|
289
|
+
return STATUS[domain2][key];
|
|
290
|
+
}
|
|
291
|
+
function statusEntries(domain2) {
|
|
292
|
+
return Object.entries(STATUS[domain2]);
|
|
293
|
+
}
|
|
294
|
+
function statusKeysWithTone(domain2, tone) {
|
|
295
|
+
return statusEntries(domain2).filter(([, meta]) => meta.tone === tone).map(([key]) => key);
|
|
296
|
+
}
|
|
297
|
+
export {
|
|
298
|
+
STATUS,
|
|
299
|
+
statusEntries,
|
|
300
|
+
statusKeysWithTone,
|
|
301
|
+
statusMeta
|
|
302
|
+
};
|
|
303
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/status.ts"],"sourcesContent":["import type { Tone } from \"@tea-ui/tokens\";\n\n/**\n * TEA UI — the status registry.\n *\n * This is the single place a wire value becomes a word and a tone. The audit of\n * the two source projects found, between them, five hand-written\n * status-to-label tables *per project*, none of which agreed — including for\n * the same wire value, where one project said \"Online\" and the other said\n * \"Läuft\" for the same state, and one used \"Gültig\" where the other used\n * \"Online\" for a certificate.\n *\n * Here, that decision has been made once. A component asks\n * `statusMeta(\"health\", \"online\")` and gets `{ label, tone, description }`.\n * There is no other supported way to render a status, which is what makes\n * cross-product consistency enforceable rather than aspirational.\n *\n * Rules this registry encodes:\n * - `tone` is always one of the five semantic tones. Never a raw colour.\n * - `label` is what the user reads. Short, nominal, no punctuation.\n * - `description` exists for every entry so a tooltip or a help affordance is\n * always available, and so nobody has to invent one at the call site.\n * - A tone never depends on colour alone: {@link StatusDot} and\n * `StatusBadge` always pair the tone with a label, and `Status` pairs it\n * with a shape. Colour is the third signal, never the only one.\n */\n\nexport type { Tone };\n\nexport interface StatusMeta {\n /** The word a user reads. Nominal, no trailing punctuation. */\n readonly label: string;\n /** The closed semantic tone. The only way a status reaches a colour. */\n readonly tone: Tone;\n /** One sentence explaining the state, for a tooltip or help text. */\n readonly description: string;\n}\n\ntype Domain<K extends string> = Readonly<Record<K, StatusMeta>>;\n\nfunction domain<K extends string>(entries: Record<K, StatusMeta>): Domain<K> {\n return entries;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Domains */\n/* -------------------------------------------------------------------------- */\n\nconst HEALTH = domain<\"online\" | \"degraded\" | \"offline\" | \"unknown\" | \"maintenance\">({\n online: {\n label: \"Online\",\n tone: \"positive\",\n description: \"Der Dienst antwortet normal und erfüllt seine Aufgabe.\",\n },\n degraded: {\n label: \"Eingeschränkt\",\n tone: \"caution\",\n description: \"Der Dienst antwortet, aber einzelne Funktionen sind nicht verfügbar.\",\n },\n offline: {\n label: \"Offline\",\n tone: \"critical\",\n description: \"Der Dienst ist nicht erreichbar.\",\n },\n unknown: {\n label: \"Unbekannt\",\n tone: \"neutral\",\n description: \"Es liegt keine aktuelle Messung vor.\",\n },\n maintenance: {\n label: \"Wartung\",\n tone: \"info\",\n description: \"Der Dienst wird geplant bearbeitet und ist möglicherweise nicht verfügbar.\",\n },\n});\n\nconst RESOURCE = domain<\"normal\" | \"elevated\" | \"high\" | \"critical\">({\n normal: {\n label: \"Normal\",\n tone: \"positive\",\n description: \"Die Auslastung liegt im üblichen Bereich.\",\n },\n elevated: {\n label: \"Erhöht\",\n tone: \"caution\",\n description: \"Die Auslastung nähert sich dem Grenzwert.\",\n },\n high: {\n label: \"Hoch\",\n tone: \"caution\",\n description: \"Die Auslastung liegt über dem Zielwert und sollte beobachtet werden.\",\n },\n critical: {\n label: \"Kritisch\",\n tone: \"critical\",\n description: \"Die Auslastung hat den Grenzwert überschritten. Handeln ist erforderlich.\",\n },\n});\n\nconst BACKUP = domain<\"succeeded\" | \"running\" | \"pending\" | \"failed\" | \"expired\">({\n succeeded: {\n label: \"Erfolgreich\",\n tone: \"positive\",\n description: \"Die Sicherung wurde vollständig geschrieben und geprüft.\",\n },\n running: {\n label: \"Läuft\",\n tone: \"info\",\n description: \"Die Sicherung wird gerade geschrieben.\",\n },\n pending: {\n label: \"Ausstehend\",\n tone: \"neutral\",\n description: \"Die Sicherung ist geplant, aber noch nicht gestartet.\",\n },\n failed: {\n label: \"Fehlgeschlagen\",\n tone: \"critical\",\n description: \"Die Sicherung wurde abgebrochen und ist nicht verwendbar.\",\n },\n expired: {\n label: \"Abgelaufen\",\n tone: \"caution\",\n description: \"Die Sicherung ist älter als die Aufbewahrungsfrist.\",\n },\n});\n\nconst CERTIFICATE = domain<\"valid\" | \"expiring\" | \"expired\" | \"invalid\" | \"unknown\">({\n valid: {\n label: \"Gültig\",\n tone: \"positive\",\n description: \"Das Zertifikat ist gültig und wird automatisch erneuert.\",\n },\n expiring: {\n label: \"Läuft ab\",\n tone: \"caution\",\n description: \"Das Zertifikat läuft in Kürze ab und sollte erneuert werden.\",\n },\n expired: {\n label: \"Abgelaufen\",\n tone: \"critical\",\n description: \"Das Zertifikat ist abgelaufen. Die Verbindung ist nicht mehr vertrauenswürdig.\",\n },\n invalid: {\n label: \"Ungültig\",\n tone: \"critical\",\n description: \"Das Zertifikat konnte nicht geprüft werden.\",\n },\n unknown: {\n label: \"Unbekannt\",\n tone: \"neutral\",\n description: \"Es liegt keine aktuelle Prüfung vor.\",\n },\n});\n\nconst CONTAINER = domain<\"running\" | \"created\" | \"paused\" | \"restarting\" | \"stopped\" | \"error\">({\n running: {\n label: \"Läuft\",\n tone: \"positive\",\n description: \"Der Container ist gestartet und wird ausgeführt.\",\n },\n created: {\n label: \"Erstellt\",\n tone: \"neutral\",\n description: \"Der Container ist angelegt, aber nicht gestartet.\",\n },\n paused: {\n label: \"Pausiert\",\n tone: \"info\",\n description: \"Der Container ist angehalten und speichert seinen Zustand.\",\n },\n restarting: {\n label: \"Startet neu\",\n tone: \"info\",\n description: \"Der Container wird gerade neu gestartet.\",\n },\n stopped: {\n label: \"Gestoppt\",\n tone: \"neutral\",\n description: \"Der Container ist gestoppt.\",\n },\n error: {\n label: \"Fehler\",\n tone: \"critical\",\n description: \"Der Container läuft nicht, weil ein Fehler aufgetreten ist.\",\n },\n});\n\nconst WEBSITE = domain<\"online\" | \"deploying\" | \"degraded\" | \"offline\" | \"error\" | \"unknown\">({\n online: {\n label: \"Online\",\n tone: \"positive\",\n description: \"Die Website ist erreichbar und wird ausgeliefert.\",\n },\n deploying: {\n label: \"Wird ausgerollt\",\n tone: \"info\",\n description: \"Eine neue Version wird gerade veröffentlicht.\",\n },\n degraded: {\n label: \"Eingeschränkt\",\n tone: \"caution\",\n description: \"Die Website ist erreichbar, hat aber Performance- oder Zertifikatsprobleme.\",\n },\n offline: {\n label: \"Offline\",\n tone: \"critical\",\n description: \"Die Website ist nicht erreichbar.\",\n },\n error: {\n label: \"Fehler\",\n tone: \"critical\",\n description: \"Beim Ausliefern der Website ist ein Fehler aufgetreten.\",\n },\n unknown: {\n label: \"Unbekannt\",\n tone: \"neutral\",\n description: \"Es liegt keine aktuelle Prüfung vor.\",\n },\n});\n\nconst DEPENDENCY = domain<\"ok\" | \"warning\" | \"missing\" | \"error\">({\n ok: { label: \"In Ordnung\", tone: \"positive\", description: \"Die Abhängigkeit ist vorhanden und aktuell.\" },\n warning: {\n label: \"Warnung\",\n tone: \"caution\",\n description: \"Die Abhängigkeit ist veraltet oder auffällig.\",\n },\n missing: {\n label: \"Fehlt\",\n tone: \"critical\",\n description: \"Die Abhängigkeit wird benötigt, ist aber nicht installiert.\",\n },\n error: {\n label: \"Fehler\",\n tone: \"critical\",\n description: \"Die Abhängigkeit konnte nicht geprüft werden.\",\n },\n});\n\nconst SECURITY = domain<\"ok\" | \"warning\" | \"critical\">({\n ok: { label: \"In Ordnung\", tone: \"positive\", description: \"Es wurde kein Problem gefunden.\" },\n warning: {\n label: \"Warnung\",\n tone: \"caution\",\n description: \"Es wurde ein Problem mit geringer Risiko gefunden.\",\n },\n critical: {\n label: \"Kritisch\",\n tone: \"critical\",\n description: \"Es wurde ein Problem mit hohem Risiko gefunden, das sofort behoben werden sollte.\",\n },\n});\n\nconst CRM = domain<\n | \"unprocessed\"\n | \"no_website\"\n | \"opportunity\"\n | \"contacted\"\n | \"conversation\"\n | \"offer\"\n | \"customer\"\n | \"archived\"\n>({\n unprocessed: {\n label: \"Unbearbeitet\",\n tone: \"neutral\",\n description: \"Der Eintrag wurde erfasst, aber noch nicht bewertet.\",\n },\n no_website: {\n label: \"Ohne Website\",\n tone: \"neutral\",\n description: \"Für den Eintrag wurde keine Website gefunden.\",\n },\n opportunity: {\n label: \"Interesse\",\n tone: \"info\",\n description: \"Es gibt einen Hinweis auf Interesse, aber noch keinen Kontakt.\",\n },\n contacted: {\n label: \"Kontaktiert\",\n tone: \"info\",\n description: \"Erster Kontakt hergestellt, Antwort steht aus.\",\n },\n conversation: {\n label: \"Im Gespräch\",\n tone: \"info\",\n description: \"Es findet ein aktiver Austausch über das Angebot statt.\",\n },\n offer: {\n label: \"Angebot\",\n tone: \"caution\",\n description: \"Ein Angebot wurde erstellt und wartet auf eine Entscheidung.\",\n },\n customer: {\n label: \"Kunde\",\n tone: \"positive\",\n description: \"Der Einstieg ist abgeschlossen.\",\n },\n archived: {\n label: \"Archiviert\",\n tone: \"neutral\",\n description: \"Der Eintrag ist abgeschlossen und wird nicht weiter bearbeitet.\",\n },\n});\n\nconst PROJECT = domain<\"planning\" | \"active\" | \"on_hold\" | \"review\" | \"delivered\" | \"cancelled\">({\n planning: {\n label: \"In Planung\",\n tone: \"neutral\",\n description: \"Das Projekt ist eingeplant, aber noch nicht gestartet.\",\n },\n active: {\n label: \"In Arbeit\",\n tone: \"info\",\n description: \"Das Projekt wird gerade umgesetzt.\",\n },\n on_hold: {\n label: \"Pausiert\",\n tone: \"caution\",\n description: \"Das Projekt ruht und wartet auf eine Entscheidung oder Zuarbeit.\",\n },\n review: {\n label: \"In Prüfung\",\n tone: \"caution\",\n description: \"Das Ergebnis wird geprüft und abgenommen.\",\n },\n delivered: {\n label: \"Abgeschlossen\",\n tone: \"positive\",\n description: \"Das Projekt ist abgenommen.\",\n },\n cancelled: {\n label: \"Abgebrochen\",\n tone: \"neutral\",\n description: \"Das Projekt wurde abgebrochen und wird nicht weiterverfolgt.\",\n },\n});\n\n/* -------------------------------------------------------------------------- */\n/* The registry */\n/* -------------------------------------------------------------------------- */\n\nexport const STATUS = {\n health: HEALTH,\n resource: RESOURCE,\n backup: BACKUP,\n certificate: CERTIFICATE,\n container: CONTAINER,\n website: WEBSITE,\n dependency: DEPENDENCY,\n security: SECURITY,\n crm: CRM,\n project: PROJECT,\n} as const;\n\nexport type StatusDomain = keyof typeof STATUS;\n\n/** The wire values a given domain may take. */\nexport type StatusKey<D extends StatusDomain> = keyof (typeof STATUS)[D] & string;\n\n/** Union of every wire value across every domain, for exhaustive switches. */\nexport type AnyStatusKey = { [D in StatusDomain]: StatusKey<D> }[StatusDomain];\n\n/**\n * Look up the label, tone and description for a wire value.\n *\n * The key is `domain` + `key` rather than a flat string, because a flat string\n * cannot be checked: `statusMeta(\"healthy\")` would compile even if no domain\n * ever produced \"healthy\". This signature makes a typo a type error, and\n * adding a wire value without a label is a type error too — which is exactly\n * the failure mode that produced five disagreeing tables.\n */\nexport function statusMeta<D extends StatusDomain>(domain: D, key: StatusKey<D>): StatusMeta {\n return STATUS[domain][key] as StatusMeta;\n}\n\n/** Every entry of a domain, as `[key, meta]` pairs. */\nexport function statusEntries<D extends StatusDomain>(domain: D): Array<[StatusKey<D>, StatusMeta]> {\n return Object.entries(STATUS[domain]) as Array<[StatusKey<D>, StatusMeta]>;\n}\n\n/**\n * The wire values of one domain that a given tone covers, in registry order.\n * Used by filter chips and legends, so a filter row can never invent a\n * category the registry does not know.\n */\nexport function statusKeysWithTone<D extends StatusDomain>(domain: D, tone: Tone): Array<StatusKey<D>> {\n return statusEntries(domain)\n .filter(([, meta]) => meta.tone === tone)\n .map(([key]) => key);\n}\n"],"mappings":"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","names":["domain"]}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TEA UI — the terminology deck.
|
|
3
|
+
*
|
|
4
|
+
* One language across the whole ecosystem. The audit found two orthographies
|
|
5
|
+
* (one project transliterating every umlaut), two registers of address, and
|
|
6
|
+
* several different German words for the same state — including "Online" and
|
|
7
|
+
* "Läuft" used interchangeably for the same wire value. Copy is treated here
|
|
8
|
+
* as a token: a component imports the word rather than typing it, so a change
|
|
9
|
+
* of vocabulary is one edit and not a search across eleven packages.
|
|
10
|
+
*
|
|
11
|
+
* Decisions encoded below:
|
|
12
|
+
* - Register: **du**. TEA's internal products address the operator directly.
|
|
13
|
+
* Public marketing pages may use a neutral voice, but never a third one.
|
|
14
|
+
* - Orthography: **real umlauts**. The transliteration pipeline that produced
|
|
15
|
+
* "Gespraech" also produced Chinese and Portuguese inside German sentences,
|
|
16
|
+
* which is evidence of a broken pipeline rather than a style.
|
|
17
|
+
* - Buttons name the *action*, not the object. "Server starten", not "Start".
|
|
18
|
+
*/
|
|
19
|
+
declare const COPY: {
|
|
20
|
+
readonly actions: {
|
|
21
|
+
readonly save: "Speichern";
|
|
22
|
+
readonly cancel: "Abbrechen";
|
|
23
|
+
readonly close: "Schließen";
|
|
24
|
+
readonly confirm: "Bestätigen";
|
|
25
|
+
readonly delete: "Löschen";
|
|
26
|
+
readonly remove: "Entfernen";
|
|
27
|
+
readonly create: "Erstellen";
|
|
28
|
+
readonly add: "Hinzufügen";
|
|
29
|
+
readonly edit: "Bearbeiten";
|
|
30
|
+
readonly duplicate: "Duplizieren";
|
|
31
|
+
readonly rename: "Umbenennen";
|
|
32
|
+
readonly move: "Verschieben";
|
|
33
|
+
readonly copy: "Kopieren";
|
|
34
|
+
readonly copied: "Kopiert";
|
|
35
|
+
readonly download: "Herunterladen";
|
|
36
|
+
readonly upload: "Hochladen";
|
|
37
|
+
readonly import: "Importieren";
|
|
38
|
+
readonly export: "Exportieren";
|
|
39
|
+
readonly refresh: "Aktualisieren";
|
|
40
|
+
readonly retry: "Erneut versuchen";
|
|
41
|
+
readonly search: "Suchen";
|
|
42
|
+
readonly filter: "Filtern";
|
|
43
|
+
readonly reset: "Zurücksetzen";
|
|
44
|
+
readonly apply: "Anwenden";
|
|
45
|
+
readonly back: "Zurück";
|
|
46
|
+
readonly next: "Weiter";
|
|
47
|
+
readonly finish: "Fertigstellen";
|
|
48
|
+
readonly start: "Starten";
|
|
49
|
+
readonly stop: "Stoppen";
|
|
50
|
+
readonly restart: "Neu starten";
|
|
51
|
+
readonly pause: "Pausieren";
|
|
52
|
+
readonly resume: "Fortsetzen";
|
|
53
|
+
readonly open: "Öffnen";
|
|
54
|
+
readonly preview: "Vorschau";
|
|
55
|
+
readonly details: "Details";
|
|
56
|
+
readonly settings: "Einstellungen";
|
|
57
|
+
readonly signIn: "Anmelden";
|
|
58
|
+
readonly signOut: "Abmelden";
|
|
59
|
+
readonly undo: "Rückgängig";
|
|
60
|
+
readonly redo: "Wiederholen";
|
|
61
|
+
};
|
|
62
|
+
readonly states: {
|
|
63
|
+
readonly loading: "Wird geladen";
|
|
64
|
+
readonly refreshing: "Wird aktualisiert";
|
|
65
|
+
readonly processing: "Wird verarbeitet";
|
|
66
|
+
readonly saving: "Wird gespeichert";
|
|
67
|
+
readonly empty: "Keine Einträge";
|
|
68
|
+
readonly error: "Fehler";
|
|
69
|
+
readonly success: "Erfolgreich";
|
|
70
|
+
readonly offline: "Offline";
|
|
71
|
+
readonly stale: "Veraltete Daten";
|
|
72
|
+
readonly readOnly: "Nur lesbar";
|
|
73
|
+
readonly required: "Pflichtfeld";
|
|
74
|
+
readonly optional: "Optional";
|
|
75
|
+
};
|
|
76
|
+
readonly navigation: {
|
|
77
|
+
readonly main: "Hauptnavigation";
|
|
78
|
+
readonly breadcrumb: "Brotkrümelnavigation";
|
|
79
|
+
readonly pagination: "Seitennavigation";
|
|
80
|
+
readonly toolbar: "Werkzeugleiste";
|
|
81
|
+
readonly skipToContent: "Zum Inhalt springen";
|
|
82
|
+
readonly openMenu: "Menü öffnen";
|
|
83
|
+
readonly closeMenu: "Menü schließen";
|
|
84
|
+
readonly toggleSidebar: "Navigation ein-/ausblenden";
|
|
85
|
+
readonly commandPalette: "Befehlspalette";
|
|
86
|
+
readonly search: "Suche";
|
|
87
|
+
};
|
|
88
|
+
readonly destructive: {
|
|
89
|
+
readonly undoTitle: "Rückgängig gemacht";
|
|
90
|
+
readonly confirmTitle: "Wirklich fortfahren?";
|
|
91
|
+
readonly typeToConfirm: "Zum Bestätigen {name} eingeben";
|
|
92
|
+
readonly irreversibleNote: "Das kann nicht rückgängig gemacht werden.";
|
|
93
|
+
};
|
|
94
|
+
readonly a11y: {
|
|
95
|
+
readonly close: "Schließen";
|
|
96
|
+
readonly open: "Öffnen";
|
|
97
|
+
readonly loading: "Wird geladen";
|
|
98
|
+
readonly requiredField: "Pflichtfeld";
|
|
99
|
+
readonly invalidField: "Eingabe ungültig";
|
|
100
|
+
readonly more: "Mehr";
|
|
101
|
+
readonly less: "Weniger";
|
|
102
|
+
readonly selected: "Ausgewählt";
|
|
103
|
+
readonly expand: "Ausklappen";
|
|
104
|
+
readonly collapse: "Einklappen";
|
|
105
|
+
readonly page: "Seite";
|
|
106
|
+
readonly of: "von";
|
|
107
|
+
readonly rowsPerPage: "Zeilen pro Seite";
|
|
108
|
+
readonly selectedRows: "{count} ausgewählt";
|
|
109
|
+
};
|
|
110
|
+
readonly formatting: {
|
|
111
|
+
readonly lastUpdated: "Zuletzt aktualisiert";
|
|
112
|
+
readonly never: "Nie";
|
|
113
|
+
readonly justNow: "Gerade eben";
|
|
114
|
+
readonly minutesAgo: "Vor {n} Min.";
|
|
115
|
+
readonly hoursAgo: "Vor {n} Std.";
|
|
116
|
+
readonly daysAgo: "Vor {n} Tg.";
|
|
117
|
+
readonly andMore: "und {n} weitere";
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
/** Substitute `{name}` placeholders. Kept here so every surface does it once. */
|
|
121
|
+
declare function fill(template: string, values: Record<string, string | number>): string;
|
|
122
|
+
/**
|
|
123
|
+
* Words TEA UI does not use, and what it uses instead. A short list, because a
|
|
124
|
+
* deck nobody reads is a deck nobody follows.
|
|
125
|
+
*/
|
|
126
|
+
declare const FORBIDDEN_COPY: ReadonlyArray<{
|
|
127
|
+
avoid: string;
|
|
128
|
+
use: string;
|
|
129
|
+
why: string;
|
|
130
|
+
}>;
|
|
131
|
+
/**
|
|
132
|
+
* Interpersonal register. Public marketing may use this, and it is the only
|
|
133
|
+
* alternative permitted; the informal form is the product default.
|
|
134
|
+
*/
|
|
135
|
+
declare const REGISTER: {
|
|
136
|
+
readonly product: "du";
|
|
137
|
+
readonly publicNeutral: "neutral";
|
|
138
|
+
};
|
|
139
|
+
type Register = (typeof REGISTER)[keyof typeof REGISTER];
|
|
140
|
+
|
|
141
|
+
export { COPY, FORBIDDEN_COPY, REGISTER, type Register, fill };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const COPY = {
|
|
2
|
+
/* --- actions: verb-first, concrete, no "Bitte" ------------------------- */
|
|
3
|
+
actions: {
|
|
4
|
+
save: "Speichern",
|
|
5
|
+
cancel: "Abbrechen",
|
|
6
|
+
close: "Schlie\xDFen",
|
|
7
|
+
confirm: "Best\xE4tigen",
|
|
8
|
+
delete: "L\xF6schen",
|
|
9
|
+
remove: "Entfernen",
|
|
10
|
+
create: "Erstellen",
|
|
11
|
+
add: "Hinzuf\xFCgen",
|
|
12
|
+
edit: "Bearbeiten",
|
|
13
|
+
duplicate: "Duplizieren",
|
|
14
|
+
rename: "Umbenennen",
|
|
15
|
+
move: "Verschieben",
|
|
16
|
+
copy: "Kopieren",
|
|
17
|
+
copied: "Kopiert",
|
|
18
|
+
download: "Herunterladen",
|
|
19
|
+
upload: "Hochladen",
|
|
20
|
+
import: "Importieren",
|
|
21
|
+
export: "Exportieren",
|
|
22
|
+
refresh: "Aktualisieren",
|
|
23
|
+
retry: "Erneut versuchen",
|
|
24
|
+
search: "Suchen",
|
|
25
|
+
filter: "Filtern",
|
|
26
|
+
reset: "Zur\xFCcksetzen",
|
|
27
|
+
apply: "Anwenden",
|
|
28
|
+
back: "Zur\xFCck",
|
|
29
|
+
next: "Weiter",
|
|
30
|
+
finish: "Fertigstellen",
|
|
31
|
+
start: "Starten",
|
|
32
|
+
stop: "Stoppen",
|
|
33
|
+
restart: "Neu starten",
|
|
34
|
+
pause: "Pausieren",
|
|
35
|
+
resume: "Fortsetzen",
|
|
36
|
+
open: "\xD6ffnen",
|
|
37
|
+
preview: "Vorschau",
|
|
38
|
+
details: "Details",
|
|
39
|
+
settings: "Einstellungen",
|
|
40
|
+
signIn: "Anmelden",
|
|
41
|
+
signOut: "Abmelden",
|
|
42
|
+
undo: "R\xFCckg\xE4ngig",
|
|
43
|
+
redo: "Wiederholen"
|
|
44
|
+
},
|
|
45
|
+
/* --- states ------------------------------------------------------------ */
|
|
46
|
+
states: {
|
|
47
|
+
loading: "Wird geladen",
|
|
48
|
+
refreshing: "Wird aktualisiert",
|
|
49
|
+
processing: "Wird verarbeitet",
|
|
50
|
+
saving: "Wird gespeichert",
|
|
51
|
+
empty: "Keine Eintr\xE4ge",
|
|
52
|
+
error: "Fehler",
|
|
53
|
+
success: "Erfolgreich",
|
|
54
|
+
offline: "Offline",
|
|
55
|
+
stale: "Veraltete Daten",
|
|
56
|
+
readOnly: "Nur lesbar",
|
|
57
|
+
required: "Pflichtfeld",
|
|
58
|
+
optional: "Optional"
|
|
59
|
+
},
|
|
60
|
+
/* --- navigation -------------------------------------------------------- */
|
|
61
|
+
navigation: {
|
|
62
|
+
main: "Hauptnavigation",
|
|
63
|
+
breadcrumb: "Brotkr\xFCmelnavigation",
|
|
64
|
+
pagination: "Seitennavigation",
|
|
65
|
+
toolbar: "Werkzeugleiste",
|
|
66
|
+
skipToContent: "Zum Inhalt springen",
|
|
67
|
+
openMenu: "Men\xFC \xF6ffnen",
|
|
68
|
+
closeMenu: "Men\xFC schlie\xDFen",
|
|
69
|
+
toggleSidebar: "Navigation ein-/ausblenden",
|
|
70
|
+
commandPalette: "Befehlspalette",
|
|
71
|
+
search: "Suche"
|
|
72
|
+
},
|
|
73
|
+
/* --- destructive ------------------------------------------------------- */
|
|
74
|
+
destructive: {
|
|
75
|
+
undoTitle: "R\xFCckg\xE4ngig gemacht",
|
|
76
|
+
confirmTitle: "Wirklich fortfahren?",
|
|
77
|
+
typeToConfirm: "Zum Best\xE4tigen {name} eingeben",
|
|
78
|
+
irreversibleNote: "Das kann nicht r\xFCckg\xE4ngig gemacht werden."
|
|
79
|
+
},
|
|
80
|
+
/* --- a11y -------------------------------------------------------------- */
|
|
81
|
+
a11y: {
|
|
82
|
+
close: "Schlie\xDFen",
|
|
83
|
+
open: "\xD6ffnen",
|
|
84
|
+
loading: "Wird geladen",
|
|
85
|
+
requiredField: "Pflichtfeld",
|
|
86
|
+
invalidField: "Eingabe ung\xFCltig",
|
|
87
|
+
more: "Mehr",
|
|
88
|
+
less: "Weniger",
|
|
89
|
+
selected: "Ausgew\xE4hlt",
|
|
90
|
+
expand: "Ausklappen",
|
|
91
|
+
collapse: "Einklappen",
|
|
92
|
+
page: "Seite",
|
|
93
|
+
of: "von",
|
|
94
|
+
rowsPerPage: "Zeilen pro Seite",
|
|
95
|
+
selectedRows: "{count} ausgew\xE4hlt"
|
|
96
|
+
},
|
|
97
|
+
/* --- formatting -------------------------------------------------------- */
|
|
98
|
+
formatting: {
|
|
99
|
+
lastUpdated: "Zuletzt aktualisiert",
|
|
100
|
+
never: "Nie",
|
|
101
|
+
justNow: "Gerade eben",
|
|
102
|
+
minutesAgo: "Vor {n} Min.",
|
|
103
|
+
hoursAgo: "Vor {n} Std.",
|
|
104
|
+
daysAgo: "Vor {n} Tg.",
|
|
105
|
+
andMore: "und {n} weitere"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
function fill(template, values) {
|
|
109
|
+
return template.replace(
|
|
110
|
+
/\{(\w+)\}/g,
|
|
111
|
+
(match, key) => key in values ? String(values[key]) : match
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
const FORBIDDEN_COPY = [
|
|
115
|
+
{
|
|
116
|
+
avoid: "Bitte",
|
|
117
|
+
use: "the verb, directly",
|
|
118
|
+
why: "Polite filler that hides the action and lengthens every label."
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
avoid: "Okay / OK",
|
|
122
|
+
use: "the specific action, or nothing",
|
|
123
|
+
why: "A button labelled OK is a button nobody can find by reading."
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
avoid: "Etwas ist schiefgelaufen",
|
|
127
|
+
use: "the error title plus the reason",
|
|
128
|
+
why: "States that nothing, and asks the user to do the diagnosis."
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
avoid: "Fehler 500",
|
|
132
|
+
use: "Serverfehler plus a next step",
|
|
133
|
+
why: "A status code is for logs, not for the person who hit the problem."
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
avoid: "Klicken Sie hier",
|
|
137
|
+
use: "a named control: \u201ESpeichern\u201C",
|
|
138
|
+
why: "Describes a mouse gesture instead of the outcome."
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
avoid: "Start / Stop as a bare label",
|
|
142
|
+
use: "Server starten / Server stoppen",
|
|
143
|
+
why: "A bare verb is ambiguous when several actions share a row."
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
avoid: "IP-Adresse (text as label)",
|
|
147
|
+
use: "IPv4-Adresse",
|
|
148
|
+
why: "Confusing two protocols under one name."
|
|
149
|
+
}
|
|
150
|
+
];
|
|
151
|
+
const REGISTER = {
|
|
152
|
+
product: "du",
|
|
153
|
+
publicNeutral: "neutral"
|
|
154
|
+
};
|
|
155
|
+
export {
|
|
156
|
+
COPY,
|
|
157
|
+
FORBIDDEN_COPY,
|
|
158
|
+
REGISTER,
|
|
159
|
+
fill
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=terminology.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/terminology.ts"],"sourcesContent":["/**\n * TEA UI — the terminology deck.\n *\n * One language across the whole ecosystem. The audit found two orthographies\n * (one project transliterating every umlaut), two registers of address, and\n * several different German words for the same state — including \"Online\" and\n * \"Läuft\" used interchangeably for the same wire value. Copy is treated here\n * as a token: a component imports the word rather than typing it, so a change\n * of vocabulary is one edit and not a search across eleven packages.\n *\n * Decisions encoded below:\n * - Register: **du**. TEA's internal products address the operator directly.\n * Public marketing pages may use a neutral voice, but never a third one.\n * - Orthography: **real umlauts**. The transliteration pipeline that produced\n * \"Gespraech\" also produced Chinese and Portuguese inside German sentences,\n * which is evidence of a broken pipeline rather than a style.\n * - Buttons name the *action*, not the object. \"Server starten\", not \"Start\".\n */\n\nexport const COPY = {\n /* --- actions: verb-first, concrete, no \"Bitte\" ------------------------- */\n actions: {\n save: \"Speichern\",\n cancel: \"Abbrechen\",\n close: \"Schließen\",\n confirm: \"Bestätigen\",\n delete: \"Löschen\",\n remove: \"Entfernen\",\n create: \"Erstellen\",\n add: \"Hinzufügen\",\n edit: \"Bearbeiten\",\n duplicate: \"Duplizieren\",\n rename: \"Umbenennen\",\n move: \"Verschieben\",\n copy: \"Kopieren\",\n copied: \"Kopiert\",\n download: \"Herunterladen\",\n upload: \"Hochladen\",\n import: \"Importieren\",\n export: \"Exportieren\",\n refresh: \"Aktualisieren\",\n retry: \"Erneut versuchen\",\n search: \"Suchen\",\n filter: \"Filtern\",\n reset: \"Zurücksetzen\",\n apply: \"Anwenden\",\n back: \"Zurück\",\n next: \"Weiter\",\n finish: \"Fertigstellen\",\n start: \"Starten\",\n stop: \"Stoppen\",\n restart: \"Neu starten\",\n pause: \"Pausieren\",\n resume: \"Fortsetzen\",\n open: \"Öffnen\",\n preview: \"Vorschau\",\n details: \"Details\",\n settings: \"Einstellungen\",\n signIn: \"Anmelden\",\n signOut: \"Abmelden\",\n undo: \"Rückgängig\",\n redo: \"Wiederholen\",\n },\n\n /* --- states ------------------------------------------------------------ */\n states: {\n loading: \"Wird geladen\",\n refreshing: \"Wird aktualisiert\",\n processing: \"Wird verarbeitet\",\n saving: \"Wird gespeichert\",\n empty: \"Keine Einträge\",\n error: \"Fehler\",\n success: \"Erfolgreich\",\n offline: \"Offline\",\n stale: \"Veraltete Daten\",\n readOnly: \"Nur lesbar\",\n required: \"Pflichtfeld\",\n optional: \"Optional\",\n },\n\n /* --- navigation -------------------------------------------------------- */\n navigation: {\n main: \"Hauptnavigation\",\n breadcrumb: \"Brotkrümelnavigation\",\n pagination: \"Seitennavigation\",\n toolbar: \"Werkzeugleiste\",\n skipToContent: \"Zum Inhalt springen\",\n openMenu: \"Menü öffnen\",\n closeMenu: \"Menü schließen\",\n toggleSidebar: \"Navigation ein-/ausblenden\",\n commandPalette: \"Befehlspalette\",\n search: \"Suche\",\n },\n\n /* --- destructive ------------------------------------------------------- */\n destructive: {\n undoTitle: \"Rückgängig gemacht\",\n confirmTitle: \"Wirklich fortfahren?\",\n typeToConfirm: \"Zum Bestätigen {name} eingeben\",\n irreversibleNote: \"Das kann nicht rückgängig gemacht werden.\",\n },\n\n /* --- a11y -------------------------------------------------------------- */\n a11y: {\n close: \"Schließen\",\n open: \"Öffnen\",\n loading: \"Wird geladen\",\n requiredField: \"Pflichtfeld\",\n invalidField: \"Eingabe ungültig\",\n more: \"Mehr\",\n less: \"Weniger\",\n selected: \"Ausgewählt\",\n expand: \"Ausklappen\",\n collapse: \"Einklappen\",\n page: \"Seite\",\n of: \"von\",\n rowsPerPage: \"Zeilen pro Seite\",\n selectedRows: \"{count} ausgewählt\",\n },\n\n /* --- formatting -------------------------------------------------------- */\n formatting: {\n lastUpdated: \"Zuletzt aktualisiert\",\n never: \"Nie\",\n justNow: \"Gerade eben\",\n minutesAgo: \"Vor {n} Min.\",\n hoursAgo: \"Vor {n} Std.\",\n daysAgo: \"Vor {n} Tg.\",\n andMore: \"und {n} weitere\",\n },\n} as const;\n\n/** Substitute `{name}` placeholders. Kept here so every surface does it once. */\nexport function fill(template: string, values: Record<string, string | number>): string {\n return template.replace(/\\{(\\w+)\\}/g, (match, key: string) =>\n key in values ? String(values[key]) : match,\n );\n}\n\n/**\n * Words TEA UI does not use, and what it uses instead. A short list, because a\n * deck nobody reads is a deck nobody follows.\n */\nexport const FORBIDDEN_COPY: ReadonlyArray<{ avoid: string; use: string; why: string }> = [\n {\n avoid: \"Bitte\",\n use: \"the verb, directly\",\n why: \"Polite filler that hides the action and lengthens every label.\",\n },\n {\n avoid: \"Okay / OK\",\n use: \"the specific action, or nothing\",\n why: \"A button labelled OK is a button nobody can find by reading.\",\n },\n {\n avoid: \"Etwas ist schiefgelaufen\",\n use: \"the error title plus the reason\",\n why: \"States that nothing, and asks the user to do the diagnosis.\",\n },\n {\n avoid: \"Fehler 500\",\n use: \"Serverfehler plus a next step\",\n why: \"A status code is for logs, not for the person who hit the problem.\",\n },\n {\n avoid: \"Klicken Sie hier\",\n use: \"a named control: „Speichern“\",\n why: \"Describes a mouse gesture instead of the outcome.\",\n },\n {\n avoid: \"Start / Stop as a bare label\",\n use: \"Server starten / Server stoppen\",\n why: \"A bare verb is ambiguous when several actions share a row.\",\n },\n {\n avoid: \"IP-Adresse (text as label)\",\n use: \"IPv4-Adresse\",\n why: \"Confusing two protocols under one name.\",\n },\n];\n\n/**\n * Interpersonal register. Public marketing may use this, and it is the only\n * alternative permitted; the informal form is the product default.\n */\nexport const REGISTER = {\n product: \"du\",\n publicNeutral: \"neutral\",\n} as const;\n\nexport type Register = (typeof REGISTER)[keyof typeof REGISTER];\n"],"mappings":"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","names":[]}
|