@cosmicdrift/kumiko-renderer 0.206.0 → 0.208.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.208.0",
|
|
4
4
|
"description": "Platform-agnostic React renderer for Kumiko screens. Contains the shared logic — primitives-contract, hooks, KumikoScreen, navigation & SSE abstractions — that any platform-specific renderer (web, native) composes. No DOM, no EventSource, no react-dom.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
}
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
19
|
-
"@cosmicdrift/kumiko-headless": "0.
|
|
18
|
+
"@cosmicdrift/kumiko-framework": "0.208.0",
|
|
19
|
+
"@cosmicdrift/kumiko-headless": "0.208.0",
|
|
20
20
|
"react": "^19.2.6",
|
|
21
21
|
"temporal-polyfill": "^0.3.2",
|
|
22
22
|
"zod": "^4.4.3"
|
|
@@ -24,7 +24,8 @@
|
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@testing-library/react": "^16.3.2",
|
|
26
26
|
"@types/react": "^19.2.14",
|
|
27
|
-
"jsdom": "^29.1.1"
|
|
27
|
+
"jsdom": "^29.1.1",
|
|
28
|
+
"@cosmicdrift/kumiko-locale-de": "0.208.0"
|
|
28
29
|
},
|
|
29
30
|
"repository": {
|
|
30
31
|
"type": "git",
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
ValidationError,
|
|
13
13
|
VersionConflictError,
|
|
14
14
|
} from "@cosmicdrift/kumiko-framework/errors";
|
|
15
|
+
import { localeDeBundle } from "@cosmicdrift/kumiko-locale-de";
|
|
15
16
|
import { REQUIRED_FIELD_I18N_KEY } from "../app/form-schema";
|
|
16
17
|
import { kumikoDefaultTranslations } from "../i18n-defaults";
|
|
17
18
|
|
|
@@ -40,13 +41,13 @@ const errorInstances = [
|
|
|
40
41
|
new ValidationError({ fields: [] }),
|
|
41
42
|
];
|
|
42
43
|
|
|
43
|
-
const de =
|
|
44
|
+
const de = localeDeBundle;
|
|
44
45
|
const en = kumikoDefaultTranslations["en"];
|
|
45
46
|
|
|
46
47
|
describe("kumikoDefaultTranslations covers every error i18nKey", () => {
|
|
47
48
|
for (const e of errorInstances) {
|
|
48
|
-
test(`${e.code} → ${e.i18nKey} has
|
|
49
|
-
expect(de
|
|
49
|
+
test(`${e.code} → ${e.i18nKey} has en default and de locale-package copy`, () => {
|
|
50
|
+
expect(de[e.i18nKey]).toBeTruthy();
|
|
50
51
|
expect(en?.[e.i18nKey]).toBeTruthy();
|
|
51
52
|
});
|
|
52
53
|
}
|
|
@@ -75,7 +76,7 @@ describe("kumikoDefaultTranslations covers every error i18nKey", () => {
|
|
|
75
76
|
// thrown by an error class, applied as a params.i18nKey override on a zod
|
|
76
77
|
// issue instead; still rendered through this last-resort bundle.
|
|
77
78
|
test("form-schema's required-field i18nKey has de+en default", () => {
|
|
78
|
-
expect(de
|
|
79
|
+
expect(de[REQUIRED_FIELD_I18N_KEY]).toBeTruthy();
|
|
79
80
|
expect(en?.[REQUIRED_FIELD_I18N_KEY]).toBeTruthy();
|
|
80
81
|
});
|
|
81
82
|
});
|
|
@@ -77,7 +77,7 @@ function renderField(field: EditFieldViewModel): void {
|
|
|
77
77
|
capturedBanner = undefined;
|
|
78
78
|
render(
|
|
79
79
|
<LocaleProvider
|
|
80
|
-
resolver={createStaticLocaleResolver({ locale: "
|
|
80
|
+
resolver={createStaticLocaleResolver({ locale: "en" })}
|
|
81
81
|
fallbackBundles={[kumikoDefaultTranslations]}
|
|
82
82
|
>
|
|
83
83
|
<PrimitivesProvider value={testPrimitives}>
|
|
@@ -109,7 +109,7 @@ describe.each([
|
|
|
109
109
|
renderField(field);
|
|
110
110
|
const children = capturedBanner?.children;
|
|
111
111
|
const childArray = Array.isArray(children) ? children : [children];
|
|
112
|
-
expect(childArray[0]).toBe("
|
|
112
|
+
expect(childArray[0]).toBe("This field type can't be edited here yet.");
|
|
113
113
|
const valuePreview = childArray[1] as { props: { children: unknown } } | false | undefined;
|
|
114
114
|
if (!valuePreview) throw new Error("expected a value-preview element");
|
|
115
115
|
expect(valuePreview.props.children).toBe(JSON.stringify(field.value));
|
|
@@ -121,7 +121,7 @@ describe("RenderField — unsupported-type Banner ohne Wert", () => {
|
|
|
121
121
|
renderField(baseField({ type: "jsonb", value: null }));
|
|
122
122
|
const children = capturedBanner?.children;
|
|
123
123
|
const childArray = Array.isArray(children) ? children : [children];
|
|
124
|
-
expect(childArray[0]).toBe("
|
|
124
|
+
expect(childArray[0]).toBe("This field type can't be edited here yet.");
|
|
125
125
|
expect(childArray[1]).toBeFalsy();
|
|
126
126
|
});
|
|
127
127
|
});
|
package/src/i18n-defaults.ts
CHANGED
|
@@ -11,212 +11,6 @@
|
|
|
11
11
|
import type { TranslationsByLocale } from "./i18n";
|
|
12
12
|
|
|
13
13
|
export const kumikoDefaultTranslations: TranslationsByLocale = {
|
|
14
|
-
de: {
|
|
15
|
-
// Actions — Buttons in RenderEdit, RenderList, Confirm-Dialogen.
|
|
16
|
-
"kumiko.actions.save": "Speichern",
|
|
17
|
-
"kumiko.actions.cancel": "Abbrechen",
|
|
18
|
-
"kumiko.actions.delete": "Löschen",
|
|
19
|
-
"kumiko.actions.delete-confirm": "Wirklich löschen?",
|
|
20
|
-
"kumiko.actions.reload": "Neu laden",
|
|
21
|
-
"kumiko.actions.create": "Neu",
|
|
22
|
-
"kumiko.actions.edit": "Bearbeiten",
|
|
23
|
-
"kumiko.actions.copyLink": "Link kopieren",
|
|
24
|
-
"kumiko.actions.copyLinkCopied": "Kopiert!",
|
|
25
|
-
"kumiko.actions.next": "Weiter",
|
|
26
|
-
"kumiko.actions.back": "Zurück",
|
|
27
|
-
"kumiko.actions.finish": "Abschließen",
|
|
28
|
-
|
|
29
|
-
// Wizard step chrome (RenderEdit layout.mode="wizard").
|
|
30
|
-
"kumiko.wizard.step": "Schritt {current} von {total}",
|
|
31
|
-
"kumiko.wizard.step-with-title": "Schritt {current} von {total} · {title}",
|
|
32
|
-
|
|
33
|
-
// Version — Update-Awareness-Banner (UpdateChecker).
|
|
34
|
-
"kumiko.version.update-available": "Eine neue Version ist verfügbar.",
|
|
35
|
-
|
|
36
|
-
// Toast — Self-service Docs-Link-Default (useToast docsLinkLabel).
|
|
37
|
-
"kumiko.toast.learn-more": "Mehr erfahren",
|
|
38
|
-
|
|
39
|
-
// Field — aria-Labels der Date/Timestamp-Primitives.
|
|
40
|
-
"kumiko.field.open-calendar": "Kalender öffnen",
|
|
41
|
-
"kumiko.field.dateField.placeholderYear": "J",
|
|
42
|
-
"kumiko.field.dateField.placeholderMonth": "M",
|
|
43
|
-
"kumiko.field.dateField.placeholderDay": "T",
|
|
44
|
-
"kumiko.field.time": "Uhrzeit",
|
|
45
|
-
"kumiko.field.timezone": "Zeitzone",
|
|
46
|
-
"kumiko.field.locatedTzHint": "Zeit lokal am angegebenen Ort",
|
|
47
|
-
"kumiko.field.reference-created-no-id":
|
|
48
|
-
"Datensatz wurde angelegt, konnte aber nicht automatisch ausgewählt werden. Bitte manuell auswählen.",
|
|
49
|
-
"kumiko.field.unsupported": "Dieser Feldtyp kann hier noch nicht bearbeitet werden.",
|
|
50
|
-
"kumiko.field.embedded-list.add-row": "Zeile hinzufügen",
|
|
51
|
-
"kumiko.field.embedded-list.remove-row": "Zeile entfernen",
|
|
52
|
-
"kumiko.field.embedded-list.duplicate-row": "Zeile duplizieren",
|
|
53
|
-
"kumiko.field.embedded-list.move-up": "Nach oben verschieben",
|
|
54
|
-
"kumiko.field.embedded-list.move-down": "Nach unten verschieben",
|
|
55
|
-
"kumiko.field.embedded-list.empty": "Noch keine Zeilen.",
|
|
56
|
-
"kumiko.field.embedded-list.empty-cta": "Erste Zeile hinzufügen",
|
|
57
|
-
"kumiko.field.embedded-list.paste-rows-truncated":
|
|
58
|
-
"{count} eingefügte Zeile(n) wurden verworfen (maximale Zeilenzahl erreicht).",
|
|
59
|
-
"kumiko.field.embedded-list.paste-cells-unmatched":
|
|
60
|
-
"{count} Zelle(n) hatten keine passende Option und wurden nicht geändert.",
|
|
61
|
-
|
|
62
|
-
// List — DataTable Toolbar, Empty-State, Search.
|
|
63
|
-
"kumiko.list.search-placeholder": "Suchen…",
|
|
64
|
-
"kumiko.list.empty.title": "Noch keine Einträge.",
|
|
65
|
-
"kumiko.list.empty.hint": "Lege den ersten an, um loszulegen.",
|
|
66
|
-
"kumiko.list.no-entries": "Keine Einträge.",
|
|
67
|
-
"kumiko.list.end-of-list": "— Ende der Liste —",
|
|
68
|
-
|
|
69
|
-
// Pager — Status-Zeile + Prev/Next/Page-aria-Labels (DataTable pagination="pages").
|
|
70
|
-
"kumiko.pager.status": "{from}–{to} von {total}",
|
|
71
|
-
"kumiko.pager.previousPage": "Vorherige Seite",
|
|
72
|
-
"kumiko.pager.nextPage": "Nächste Seite",
|
|
73
|
-
"kumiko.pager.page": "Seite {entry}",
|
|
74
|
-
|
|
75
|
-
// Combobox — Tier 2.1c Searchable-Select.
|
|
76
|
-
"kumiko.combobox.search-placeholder": "Suchen…",
|
|
77
|
-
"kumiko.combobox.empty": "Keine Treffer.",
|
|
78
|
-
"kumiko.combobox.loading": "Lade…",
|
|
79
|
-
|
|
80
|
-
// Dashboard — Default-Label für den "(alle)"-Eintrag im Screen-Filter,
|
|
81
|
-
// wenn DashboardFilterDefinition.allLabel nicht gesetzt ist.
|
|
82
|
-
"kumiko.dashboard.filter.all": "Alle",
|
|
83
|
-
"kumiko.combobox.placeholder": "—",
|
|
84
|
-
|
|
85
|
-
// Widgets — Query-States (QueryTable, LoadingState, ErrorState).
|
|
86
|
-
"kumiko.widget.loading": "Lade…",
|
|
87
|
-
"kumiko.widget.error.title": "Konnte nicht geladen werden.",
|
|
88
|
-
|
|
89
|
-
// Widgets — UploadZone Status-Zeile pro Datei.
|
|
90
|
-
"kumiko.widget.upload.uploading": "Wird hochgeladen…",
|
|
91
|
-
"kumiko.widget.upload.done": "Hochgeladen",
|
|
92
|
-
"kumiko.widget.upload.error": "Fehlgeschlagen",
|
|
93
|
-
"kumiko.widget.upload.rejected-type": "Dateityp nicht erlaubt",
|
|
94
|
-
|
|
95
|
-
// Widgets — StepBar screen-reader text for completed steps whose number is visually replaced by a checkmark.
|
|
96
|
-
"kumiko.widget.step-bar.done": "Erledigt",
|
|
97
|
-
|
|
98
|
-
// Widgets — Drawer resize handle + maximize toggle aria-labels.
|
|
99
|
-
"kumiko.widget.drawer.restore": "Drawer-Breite zurücksetzen",
|
|
100
|
-
"kumiko.widget.drawer.maximize": "Drawer maximieren",
|
|
101
|
-
"kumiko.widget.drawer.resize": "Drawer-Größe ändern",
|
|
102
|
-
|
|
103
|
-
// Nav — Sidebar Tree (Toggle-aria-Labels).
|
|
104
|
-
"kumiko.nav.expand": "Aufklappen",
|
|
105
|
-
"kumiko.nav.collapse": "Zuklappen",
|
|
106
|
-
"kumiko.nav.search": "Navigation durchsuchen…",
|
|
107
|
-
|
|
108
|
-
// Workspace — Switcher-Trigger aria-Label (renderer-web).
|
|
109
|
-
"kumiko.workspace.switch": "Workspace wechseln",
|
|
110
|
-
"kumiko.workspace.select": "Workspace wählen",
|
|
111
|
-
|
|
112
|
-
// Dialog — Confirm-Buttons + Close-aria-Label.
|
|
113
|
-
"kumiko.dialog.confirm": "Bestätigen",
|
|
114
|
-
"kumiko.dialog.cancel": "Abbrechen",
|
|
115
|
-
"kumiko.dialog.close": "Schließen",
|
|
116
|
-
|
|
117
|
-
// AiTextField/AiTextArea — Ghost-Text-Hint, Toolbar-Aria-Labels, Diff-Dialog.
|
|
118
|
-
"kumiko.aiText.acceptHint": "Tab = übernehmen, Esc = verwerfen",
|
|
119
|
-
"kumiko.aiText.correct": "Korrigieren",
|
|
120
|
-
"kumiko.aiText.translate": "Übersetzen",
|
|
121
|
-
"kumiko.aiText.rewrite": "Umschreiben",
|
|
122
|
-
"kumiko.aiText.diff.before": "Vorher",
|
|
123
|
-
"kumiko.aiText.diff.after": "Nachher",
|
|
124
|
-
"kumiko.aiText.diff.generating": "Wird generiert…",
|
|
125
|
-
"kumiko.aiText.style.formal": "Formell",
|
|
126
|
-
"kumiko.aiText.style.casual": "Locker",
|
|
127
|
-
"kumiko.aiText.style.concise": "Kompakt",
|
|
128
|
-
"kumiko.aiText.style.expand": "Ausführlicher",
|
|
129
|
-
"kumiko.aiText.capExceeded": "Monatliches AI-Limit erreicht.",
|
|
130
|
-
|
|
131
|
-
// Row-Actions — Fehler-Toast wenn ein Action-Write fehlschlägt.
|
|
132
|
-
"kumiko.rowAction.failed": "Aktion fehlgeschlagen",
|
|
133
|
-
|
|
134
|
-
// ContentEditor — Variablen-Chip-Leiste (VariableChips).
|
|
135
|
-
"kumiko.contentEditor.insertVariable": "{name} einfügen",
|
|
136
|
-
"kumiko.contentEditor.preview": "Vorschau",
|
|
137
|
-
"kumiko.contentEditor.editMode": "Bearbeiten",
|
|
138
|
-
"kumiko.contentEditor.bold": "Fett",
|
|
139
|
-
"kumiko.contentEditor.italic": "Kursiv",
|
|
140
|
-
"kumiko.contentEditor.heading1": "Überschrift 1",
|
|
141
|
-
"kumiko.contentEditor.heading2": "Überschrift 2",
|
|
142
|
-
"kumiko.contentEditor.bulletList": "Aufzählungsliste",
|
|
143
|
-
"kumiko.contentEditor.orderedList": "Nummerierte Liste",
|
|
144
|
-
|
|
145
|
-
// Config-Cascade — Source-Badges + Cascade-Panel (ConfigCascadeView).
|
|
146
|
-
"kumiko.config.source.user": "Mein Wert",
|
|
147
|
-
"kumiko.config.source.tenant": "Tenant",
|
|
148
|
-
"kumiko.config.source.system": "System",
|
|
149
|
-
"kumiko.config.source.appOverride": "App-Override",
|
|
150
|
-
"kumiko.config.source.computed": "Berechnet",
|
|
151
|
-
"kumiko.config.source.default": "Standard",
|
|
152
|
-
"kumiko.config.source.missing": "Fehlt",
|
|
153
|
-
"kumiko.config.cascade.noValue": "Kein Wert gesetzt",
|
|
154
|
-
"kumiko.config.cascade.activeMarker": "aktiv",
|
|
155
|
-
"kumiko.config.cascade.resetTo": "Überschreibung zurücksetzen ({scope})",
|
|
156
|
-
|
|
157
|
-
// Form — Standard-Errors (App-Code kann eigene zod-Reasons nutzen,
|
|
158
|
-
// diese sind die letzte Sicherheitsschicht).
|
|
159
|
-
"kumiko.form.error.generic": "Etwas ist schiefgegangen.",
|
|
160
|
-
"kumiko.form.error.version-conflict":
|
|
161
|
-
"Datensatz wurde zwischenzeitlich geändert. Lade neu und versuche es erneut.",
|
|
162
|
-
"kumiko.form.extension.save-failed": "Ein Zusatzfeld konnte nicht gespeichert werden.",
|
|
163
|
-
"kumiko.form.draft.resume-multiple":
|
|
164
|
-
"Mehrere offene Entwürfe für dieses Formular gefunden. Welchen möchtest du fortsetzen?",
|
|
165
|
-
"kumiko.form.draft.resume-single":
|
|
166
|
-
"Ein offener Entwurf für dieses Formular gefunden. Möchtest du ihn fortsetzen?",
|
|
167
|
-
"kumiko.form.draft.start-new": "Neu beginnen",
|
|
168
|
-
|
|
169
|
-
// Validation — Default-Reason-Codes aus dem Framework. App-Code
|
|
170
|
-
// kann eigene Codes via Validation-Hooks reinwerfen; die hier sind
|
|
171
|
-
// die generischen.
|
|
172
|
-
"kumiko.validation.required": "Pflichtfeld.",
|
|
173
|
-
"kumiko.validation.invalid": "Ungültiger Wert.",
|
|
174
|
-
"kumiko.validation.too-short": "Zu kurz (mindestens {min} Zeichen).",
|
|
175
|
-
"kumiko.validation.too-long": "Zu lang (höchstens {max} Zeichen).",
|
|
176
|
-
"kumiko.validation.out-of-range": "Wert außerhalb des erlaubten Bereichs.",
|
|
177
|
-
|
|
178
|
-
// errors.validation.* — der kanonische Key-Namespace den Server
|
|
179
|
-
// (ValidationError) und Client (zod-bridge) für Field-Issues
|
|
180
|
-
// erzeugen. Codes = Zod-4-Issue-Codes + Framework-eigene.
|
|
181
|
-
"errors.validation.invalid_type": "Ungültiger Wert.",
|
|
182
|
-
"errors.validation.too_small": "Zu klein oder zu kurz (Minimum: {minimum}).",
|
|
183
|
-
"errors.validation.too_big": "Zu groß oder zu lang (Maximum: {maximum}).",
|
|
184
|
-
"errors.validation.invalid_format": "Ungültiges Format.",
|
|
185
|
-
"errors.validation.not_multiple_of": "Muss ein Vielfaches von {divisor} sein.",
|
|
186
|
-
"errors.validation.unrecognized_keys": "Unbekannte Felder.",
|
|
187
|
-
"errors.validation.invalid_union": "Ungültiger Wert.",
|
|
188
|
-
"errors.validation.invalid_key": "Ungültiger Schlüssel.",
|
|
189
|
-
"errors.validation.invalid_element": "Ungültiger Eintrag.",
|
|
190
|
-
"errors.validation.invalid_value": "Ungültige Auswahl.",
|
|
191
|
-
"errors.validation.custom": "Ungültiger Wert.",
|
|
192
|
-
"errors.validation.unexpected_field": "Unbekanntes Feld.",
|
|
193
|
-
"errors.validation.out_of_bounds": "Wert außerhalb des erlaubten Bereichs.",
|
|
194
|
-
"errors.validation.invalid_option": "Ungültige Auswahl.",
|
|
195
|
-
"errors.validation.failed": "Validierung fehlgeschlagen.",
|
|
196
|
-
|
|
197
|
-
// errors.* — Top-Level-Error-Codes (eine pro httpStatus-Klasse). Letzter
|
|
198
|
-
// Fallback wenn eine App keine eigene Übersetzung liefert; bewusst
|
|
199
|
-
// generisch (keine technischen Entity-/Feature-/Key-Namen an End-User —
|
|
200
|
-
// die stecken in `details` für Devs). Apps überschreiben pro Key.
|
|
201
|
-
"errors.feature.disabled": "Diese Funktion ist derzeit nicht verfügbar.",
|
|
202
|
-
"errors.access.denied": "Dazu hast du keine Berechtigung.",
|
|
203
|
-
"errors.notFound": "Nicht gefunden.",
|
|
204
|
-
"errors.conflict": "Konflikt — der Vorgang konnte nicht abgeschlossen werden.",
|
|
205
|
-
"errors.versionConflict":
|
|
206
|
-
"Der Datensatz wurde zwischenzeitlich geändert. Lade neu und versuche es erneut.",
|
|
207
|
-
"errors.uniqueViolation": "Dieser Eintrag existiert bereits.",
|
|
208
|
-
"errors.unprocessable": "Die Anfrage konnte nicht verarbeitet werden.",
|
|
209
|
-
"errors.unconfigured": "Diese Funktion ist noch nicht konfiguriert.",
|
|
210
|
-
"errors.internal": "Etwas ist schiefgegangen. Bitte versuche es später erneut.",
|
|
211
|
-
"errors.rate_limited": "Zu viele Anfragen. Bitte versuche es in Kürze erneut.",
|
|
212
|
-
"errors.cap.exceeded":
|
|
213
|
-
"Limit erreicht. Bitte Tarif upgraden oder auf die nächste Periode warten.",
|
|
214
|
-
"errors.download.urlMissing": "Download nicht verfügbar — bitte versuche es erneut.",
|
|
215
|
-
"auth.errors.originNotAllowed": "Zugriff von dieser Herkunft ist nicht erlaubt.",
|
|
216
|
-
"dispatcher.errors.network":
|
|
217
|
-
"Netzwerkfehler. Bitte überprüfe deine Verbindung und versuche es erneut.",
|
|
218
|
-
"dispatcher.errors.aborted": "Anfrage abgebrochen.",
|
|
219
|
-
},
|
|
220
14
|
en: {
|
|
221
15
|
"kumiko.actions.save": "Save",
|
|
222
16
|
"kumiko.actions.cancel": "Cancel",
|
|
@@ -295,6 +89,7 @@ export const kumikoDefaultTranslations: TranslationsByLocale = {
|
|
|
295
89
|
"kumiko.nav.expand": "Expand",
|
|
296
90
|
"kumiko.nav.collapse": "Collapse",
|
|
297
91
|
"kumiko.nav.search": "Search navigation…",
|
|
92
|
+
"kumiko.nav.language": "Language",
|
|
298
93
|
|
|
299
94
|
"kumiko.workspace.switch": "Switch workspace",
|
|
300
95
|
// Workspace-Switcher fallback label when activeId points at no visible workspace.
|