@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.206.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.206.0",
19
- "@cosmicdrift/kumiko-headless": "0.206.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 = kumikoDefaultTranslations["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 de+en default`, () => {
49
- expect(de?.[e.i18nKey]).toBeTruthy();
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?.[REQUIRED_FIELD_I18N_KEY]).toBeTruthy();
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: "de-DE" })}
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("Dieser Feldtyp kann hier noch nicht bearbeitet werden.");
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("Dieser Feldtyp kann hier noch nicht bearbeitet werden.");
124
+ expect(childArray[0]).toBe("This field type can't be edited here yet.");
125
125
  expect(childArray[1]).toBeFalsy();
126
126
  });
127
127
  });
@@ -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.