@cosmicdrift/kumiko-bundled-features 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.
Files changed (68) hide show
  1. package/package.json +9 -8
  2. package/src/admin-shell/__tests__/admin-shell.boot.test.ts +1 -1
  3. package/src/admin-shell/i18n.ts +17 -20
  4. package/src/admin-shell/web/i18n.ts +6 -11
  5. package/src/audit/i18n.ts +25 -25
  6. package/src/audit/web/i18n.ts +5 -9
  7. package/src/auth-email-password/__tests__/email-templates.test.ts +4 -0
  8. package/src/auth-email-password/email-templates.ts +97 -149
  9. package/src/auth-email-password/i18n.ts +6 -136
  10. package/src/auth-email-password/web/__tests__/confirm-account-unlock-screen.test.tsx +7 -7
  11. package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +14 -14
  12. package/src/auth-email-password/web/__tests__/invite-accept-screen.test.tsx +23 -25
  13. package/src/auth-email-password/web/__tests__/login-screen.test.tsx +60 -68
  14. package/src/auth-email-password/web/__tests__/request-account-unlock-screen.test.tsx +24 -24
  15. package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +20 -20
  16. package/src/auth-email-password/web/__tests__/signup-complete-screen.test.tsx +9 -9
  17. package/src/auth-email-password/web/__tests__/signup-screen.test.tsx +11 -11
  18. package/src/auth-email-password/web/__tests__/test-utils.tsx +2 -2
  19. package/src/auth-email-password/web/__tests__/user-menu.test.tsx +3 -3
  20. package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +3 -3
  21. package/src/auth-email-password/web/invite-accept-screen.tsx +3 -1
  22. package/src/auth-mfa/__tests__/errors-i18n-parity.test.ts +2 -4
  23. package/src/auth-mfa/i18n.ts +1 -2
  24. package/src/auth-mfa/web/__tests__/mfa-enable-screen.test.tsx +15 -15
  25. package/src/auth-mfa/web/__tests__/mfa-setup-preauth-screen.test.tsx +45 -49
  26. package/src/auth-mfa/web/__tests__/mfa-verify-screen.test.tsx +10 -10
  27. package/src/auth-mfa/web/i18n.ts +0 -63
  28. package/src/cap-counter/i18n.ts +5 -6
  29. package/src/compliance-profiles/i18n.ts +3 -3
  30. package/src/compliance-profiles/web/i18n.ts +0 -10
  31. package/src/config/i18n.ts +5 -5
  32. package/src/config/web/i18n.ts +1 -10
  33. package/src/custom-fields/web/i18n.ts +1 -9
  34. package/src/delivery/i18n.ts +3 -3
  35. package/src/delivery/web/i18n.ts +0 -10
  36. package/src/feature-toggles/i18n.ts +3 -3
  37. package/src/feature-toggles/web/i18n.ts +0 -12
  38. package/src/folders/web/i18n.ts +1 -26
  39. package/src/jobs/i18n.ts +40 -46
  40. package/src/jobs/web/i18n.ts +5 -9
  41. package/src/managed-pages/i18n.ts +23 -27
  42. package/src/managed-pages/web/i18n.ts +6 -11
  43. package/src/notes-history/i18n.ts +1 -1
  44. package/src/notes-history/web/i18n.ts +1 -9
  45. package/src/personal-access-tokens/i18n.ts +2 -2
  46. package/src/personal-access-tokens/web/i18n.ts +0 -37
  47. package/src/sessions/i18n.ts +17 -17
  48. package/src/tags/i18n.ts +2 -2
  49. package/src/tags/web/i18n.ts +1 -27
  50. package/src/template-resolver/web/__tests__/client-plugin.test.tsx +2 -2
  51. package/src/template-resolver/web/__tests__/editor-read-only.test.tsx +5 -5
  52. package/src/template-resolver/web/i18n.ts +0 -14
  53. package/src/tenant/__tests__/members-screens.boot.test.ts +0 -2
  54. package/src/tenant/i18n.ts +13 -16
  55. package/src/tenant/web/i18n.ts +0 -19
  56. package/src/tier-engine/i18n.ts +3 -19
  57. package/src/user/i18n.ts +14 -15
  58. package/src/user-data-rights/__tests__/default-mailers.test.ts +4 -0
  59. package/src/user-data-rights/__tests__/email-templates.test.ts +4 -0
  60. package/src/user-data-rights/__tests__/mail-default-bridge.integration.test.ts +2 -0
  61. package/src/user-data-rights/__tests__/run-export-jobs-cron-context.integration.test.ts +4 -0
  62. package/src/user-data-rights/email-templates.ts +55 -91
  63. package/src/user-data-rights/i18n.ts +18 -22
  64. package/src/user-data-rights/lib/default-mailers.ts +4 -1
  65. package/src/user-data-rights/web/__tests__/deletion-screens.test.tsx +11 -11
  66. package/src/user-data-rights/web/__tests__/public-deletion-gate.test.tsx +5 -5
  67. package/src/user-data-rights/web/i18n.ts +9 -88
  68. package/src/user-profile/i18n.ts +1 -36
@@ -6,69 +6,6 @@
6
6
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
7
7
 
8
8
  export const defaultTranslations: TranslationsByLocale = {
9
- de: {
10
- "screen:auth-mfa-enable.title": "Zwei-Faktor-Authentifizierung",
11
- "auth.mfa.verify.title": "Zwei-Faktor-Bestätigung",
12
- "auth.mfa.verify.subtitle": "Gib den 6-stelligen Code aus deiner Authenticator-App ein.",
13
- "auth.mfa.verify.code": "Code",
14
- "auth.mfa.verify.submit": "Bestätigen",
15
- "auth.mfa.verify.submitting": "…",
16
- "auth.mfa.verify.backToLogin": "Zurück zum Login",
17
- "auth.mfa.errors.invalidCode": "Ungültiger Code. Bitte erneut versuchen.",
18
- "auth.mfa.errors.invalidTotpCode": "Ungültiger Code. Bitte erneut versuchen.",
19
- "auth.mfa.errors.invalidChallengeToken":
20
- "Die Anmeldung ist abgelaufen. Bitte erneut einloggen.",
21
- "auth.mfa.errors.challengeExpired": "Die Anmeldung ist abgelaufen. Bitte erneut einloggen.",
22
- "auth.mfa.errors.tooManyAttempts": "Zu viele Fehlversuche. Bitte erneut einloggen.",
23
- "auth.mfa.errors.tooManyAttemptsWithSeconds":
24
- "Zu viele Fehlversuche. Bitte in {seconds} Sekunden erneut versuchen oder neu einloggen.",
25
- "auth.mfa.errors.verifyFailed": "Bestätigung fehlgeschlagen.",
26
- "auth.mfa.errors.mfaAlreadyEnabled": "Zwei-Faktor-Authentifizierung ist bereits aktiv.",
27
- "auth.mfa.errors.mfaNotEnabled": "Zwei-Faktor-Authentifizierung ist nicht aktiv.",
28
- "auth.mfa.errors.invalidSetupToken": "Die Einrichtung ist abgelaufen. Bitte erneut starten.",
29
- "auth.mfa.errors.setupFailed": "Einrichtung fehlgeschlagen. Bitte erneut versuchen.",
30
- "auth.mfa.errors.invalidRecoveryCode": "Ungültiger Recovery-Code.",
31
- "auth.mfa.enable.title": "Zwei-Faktor-Authentifizierung",
32
- "auth.mfa.enable.intro":
33
- "Schütze dein Konto zusätzlich mit einer Authenticator-App (z.B. Google Authenticator, 1Password).",
34
- "auth.mfa.enable.start": "Einrichtung starten",
35
- "auth.mfa.enable.scanTitle": "QR-Code scannen",
36
- "auth.mfa.enable.manualEntry": "Oder manuell eingeben:",
37
- "auth.mfa.enable.recoveryTitle": "Recovery-Codes",
38
- "auth.mfa.enable.recoveryHint":
39
- "Speichere diese Codes an einem sicheren Ort. Sie werden nur dieses eine Mal angezeigt und erlauben dir den Zugriff, falls du dein Gerät verlierst.",
40
- "auth.mfa.enable.acknowledge": "Ich habe die Recovery-Codes gespeichert.",
41
- "auth.mfa.enable.code": "Code aus der Authenticator-App",
42
- "auth.mfa.enable.cancel": "Abbrechen",
43
- "auth.mfa.enable.confirm": "Aktivieren",
44
- "auth.mfa.enable.success": "Zwei-Faktor-Authentifizierung ist jetzt aktiv.",
45
- "auth.mfa.setup.title": "Zwei-Faktor-Authentifizierung erforderlich",
46
- "auth.mfa.setup.subtitle":
47
- "Dein Konto verlangt Zwei-Faktor-Authentifizierung. Richte sie jetzt ein, um dich anzumelden.",
48
- "auth.mfa.setup.intro":
49
- "Scanne den QR-Code mit einer Authenticator-App (z.B. Google Authenticator, 1Password).",
50
- "auth.mfa.setup.start": "Einrichtung starten",
51
- "auth.mfa.setup.confirm": "Einrichtung abschließen",
52
- "auth.mfa.disable.title": "Zwei-Faktor-Authentifizierung deaktivieren",
53
- "auth.mfa.disable.description":
54
- "Bestätige mit einem Code aus deiner Authenticator-App oder einem Recovery-Code. Dein Konto ist danach nur noch durch dein Passwort geschützt.",
55
- "auth.mfa.disable.code": "Code aus der Authenticator-App oder Recovery-Code",
56
- "auth.mfa.disable.confirm": "Deaktivieren",
57
- "auth.mfa.disable.cancel": "Abbrechen",
58
- "auth.mfa.disable.trigger": "Zwei-Faktor-Authentifizierung deaktivieren",
59
- "auth.mfa.regenerate.title": "Neue Recovery-Codes erzeugen",
60
- "auth.mfa.regenerate.description":
61
- "Bestätige mit einem Code aus deiner Authenticator-App. Alle bisherigen Recovery-Codes werden sofort ungültig.",
62
- "auth.mfa.regenerate.code": "Code aus der Authenticator-App",
63
- "auth.mfa.regenerate.confirm": "Neu erzeugen",
64
- "auth.mfa.regenerate.cancel": "Abbrechen",
65
- "auth.mfa.regenerate.trigger": "Neue Recovery-Codes erzeugen",
66
- "auth.mfa.regenerate.newCodesTitle": "Deine neuen Recovery-Codes",
67
- "auth.mfa.regenerate.newCodesHint":
68
- "Speichere diese Codes an einem sicheren Ort. Die alten Codes funktionieren ab sofort nicht mehr.",
69
- "auth.mfa.regenerate.acknowledge": "Ich habe die neuen Recovery-Codes gespeichert.",
70
- "auth.mfa.regenerate.done": "Fertig",
71
- },
72
9
  en: {
73
10
  "screen:auth-mfa-enable.title": "Two-factor authentication",
74
11
  "auth.mfa.verify.title": "Two-factor verification",
@@ -1,12 +1,11 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const CAP_COUNTER_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:cap-list.title": { de: "Nutzungslimits", en: "Usage caps" },
5
- "cap-counter:entity:cap-counter:field:capName": { de: "Limit", en: "Cap" },
6
- "cap-counter:entity:cap-counter:field:value": { de: "Wert", en: "Value" },
7
- "cap-counter:entity:cap-counter:field:periodStart": { de: "Periodenstart", en: "Period start" },
4
+ "screen:cap-list.title": { en: "Usage caps" },
5
+ "cap-counter:entity:cap-counter:field:capName": { en: "Cap" },
6
+ "cap-counter:entity:cap-counter:field:value": { en: "Value" },
7
+ "cap-counter:entity:cap-counter:field:periodStart": { en: "Period start" },
8
8
  "cap-counter:entity:cap-counter:field:lastSoftWarnedAt": {
9
- de: "Letzte Soft-Warnung",
10
9
  en: "Last soft warning",
11
10
  },
12
11
  };
@@ -1,6 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const COMPLIANCE_PROFILES_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:profile-picker.title": { de: "Compliance-Profil", en: "Compliance profile" },
5
- "compliance-profiles:nav.profilePicker": { de: "Compliance", en: "Compliance" },
4
+ "screen:profile-picker.title": { en: "Compliance profile" },
5
+ "compliance-profiles:nav.profilePicker": { en: "Compliance" },
6
6
  };
@@ -2,16 +2,6 @@
2
2
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
3
 
4
4
  export const defaultTranslations: TranslationsByLocale = {
5
- de: {
6
- "compliance.profile.title": "Compliance-Profil",
7
- "compliance.profile.loading": "Lade Compliance-Profile…",
8
- "compliance.profile.current": "Aktuell",
9
- "compliance.profile.select": "Profil",
10
- "compliance.profile.save": "Profil speichern",
11
- "compliance.profile.saving": "Speichert…",
12
- "compliance.profile.catalog": "Verfügbare Profile",
13
- "compliance-profiles:nav.profilePicker": "Compliance",
14
- },
15
5
  en: {
16
6
  "compliance.profile.title": "Compliance profile",
17
7
  "compliance.profile.loading": "Loading compliance profiles…",
@@ -1,9 +1,9 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  /** Server boot keys for the auto-generated Settings-Hub (mirrors web/i18n.ts). */
4
4
  export const CONFIG_FEATURE_I18N: Readonly<Record<string, LocalizedString>> = {
5
- "config.settings.title": { de: "Einstellungen", en: "Settings" },
6
- "config.settings.system": { de: "Plattform", en: "Platform" },
7
- "config.settings.tenant": { de: "Organisation", en: "Organization" },
8
- "config.settings.user": { de: "Persönlich", en: "Personal" },
5
+ "config.settings.title": { en: "Settings" },
6
+ "config.settings.system": { en: "Platform" },
7
+ "config.settings.tenant": { en: "Organization" },
8
+ "config.settings.user": { en: "Personal" },
9
9
  };
@@ -4,21 +4,12 @@
4
4
  // groups and `config.settings.title` for the synthetic workspace — generic
5
5
  // across every app, so they ship here. configClient() hangs them into the
6
6
  // LocaleProvider as a fallback; an app overrides individual keys via
7
- // configClient({ translations: { de: { ... } } }). The app only adds labels
7
+ // configClient({ translations }). The app only adds labels
8
8
  // for ITS keys (mask.title) and the per-feature group key `<feature>.settings`.
9
9
 
10
10
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
11
11
 
12
12
  export const defaultTranslations: TranslationsByLocale = {
13
- de: {
14
- "config.settings.title": "Einstellungen",
15
- "config.settings.system": "Plattform",
16
- "config.settings.tenant": "Organisation",
17
- "config.settings.user": "Persönlich",
18
- "config.errors.systemOnly": "Dieser Wert kann nur vom System gesetzt werden.",
19
- "config.errors.invalidScope": "Diese Ebene ist für diesen Schlüssel nicht zulässig.",
20
- "config.errors.unknownKey": "Unbekannter Konfigurationsschlüssel.",
21
- },
22
13
  en: {
23
14
  "config.settings.title": "Settings",
24
15
  "config.settings.system": "Platform",
@@ -1,7 +1,7 @@
1
1
  // @runtime client
2
2
  // Default translation bundle for the custom-fields UI. customFieldsClient()
3
3
  // hangs it into the LocaleProvider as a fallback bundle — apps override
4
- // individual keys via `customFieldsClient({ translations: { de: { ... } } })`.
4
+ // individual keys via `customFieldsClient({ translations })`.
5
5
  //
6
6
  // Keys follow `custom-fields.<area>.<slug>`. `custom-fields.errors.saveFailed`
7
7
  // is a LOCAL fallback only — server handlers emit generic error i18nKeys
@@ -11,14 +11,6 @@
11
11
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
12
12
 
13
13
  export const defaultTranslations: TranslationsByLocale = {
14
- de: {
15
- "custom-fields.form.createMode": "Speichere zuerst den Eintrag, um Custom-Felder zu setzen.",
16
- "custom-fields.form.loading": "Lädt…",
17
- "custom-fields.form.empty": 'Keine Custom-Felder für "{entityName}" definiert.',
18
- "custom-fields.form.save": "Custom-Felder speichern",
19
- "custom-fields.form.saving": "Speichert…",
20
- "custom-fields.errors.saveFailed": "Speichern fehlgeschlagen.",
21
- },
22
14
  en: {
23
15
  "custom-fields.form.createMode": "Save the entity first to add custom field values.",
24
16
  "custom-fields.form.loading": "Loading…",
@@ -1,6 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const DELIVERY_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:delivery-log.title": { de: "Delivery-Log", en: "Delivery log" },
5
- "delivery:nav.deliveryLog": { de: "Zustellungen", en: "Delivery" },
4
+ "screen:delivery-log.title": { en: "Delivery log" },
5
+ "delivery:nav.deliveryLog": { en: "Delivery" },
6
6
  };
@@ -2,16 +2,6 @@
2
2
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
3
 
4
4
  export const defaultTranslations: TranslationsByLocale = {
5
- de: {
6
- "delivery.log.title": "Delivery-Log",
7
- "delivery.log.loading": "Lade Zustellversuche…",
8
- "delivery.log.empty": "Keine Zustellversuche.",
9
- "delivery.log.col.type": "Typ",
10
- "delivery.log.col.channel": "Kanal",
11
- "delivery.log.col.recipient": "Empfänger",
12
- "delivery.log.col.status": "Status",
13
- "delivery:nav.deliveryLog": "Zustellungen",
14
- },
15
5
  en: {
16
6
  "delivery.log.title": "Delivery log",
17
7
  "delivery.log.loading": "Loading delivery attempts…",
@@ -1,6 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const FEATURE_TOGGLES_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:toggle-admin.title": { de: "Feature-Toggles", en: "Feature toggles" },
5
- "feature-toggles:nav.toggleAdmin": { de: "Feature-Toggles", en: "Feature toggles" },
4
+ "screen:toggle-admin.title": { en: "Feature toggles" },
5
+ "feature-toggles:nav.toggleAdmin": { en: "Feature toggles" },
6
6
  };
@@ -2,18 +2,6 @@
2
2
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
3
 
4
4
  export const defaultTranslations: TranslationsByLocale = {
5
- de: {
6
- "feature-toggles.admin.title": "Feature-Toggles",
7
- "feature-toggles.admin.loading": "Lade Feature-Toggles…",
8
- "feature-toggles.admin.col.feature": "Feature",
9
- "feature-toggles.admin.col.default": "Default",
10
- "feature-toggles.admin.col.override": "Override",
11
- "feature-toggles.admin.col.effective": "Effektiv",
12
- "feature-toggles.admin.toggle": "Umschalten",
13
- "feature-toggles.admin.saving": "Speichert…",
14
- "feature-toggles.admin.alwaysOn": "immer an",
15
- "feature-toggles:nav.toggleAdmin": "Feature-Toggles",
16
- },
17
5
  en: {
18
6
  "feature-toggles.admin.title": "Feature toggles",
19
7
  "feature-toggles.admin.loading": "Loading feature toggles…",
@@ -1,36 +1,11 @@
1
1
  // @runtime client
2
2
  // Default translation bundle for the folders UI. foldersClient() hangs it into
3
3
  // the LocaleProvider as a fallback bundle — apps override individual keys via
4
- // foldersClient({ translations: { de: { ... } } }). Keys follow `folders.<area>.<slug>`.
4
+ // foldersClient({ translations }). Keys follow `folders.<area>.<slug>`.
5
5
 
6
6
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
7
7
 
8
8
  export const defaultTranslations: TranslationsByLocale = {
9
- de: {
10
- "folders.section.createMode": "Speichere zuerst den Eintrag, um einen Ordner zu wählen.",
11
- "folders.section.loading": "Lädt…",
12
- "folders.section.label": "Ordner",
13
- "folders.section.placeholder": "Ordner auswählen…",
14
- "folders.section.empty": "Keine Ordner gefunden.",
15
- "folders.section.none": "— Kein Ordner —",
16
- "folders.section.newLabel": "Neuer Ordner",
17
- "folders.section.create": "Ordner anlegen & ablegen",
18
- "folders.section.working": "Speichert…",
19
-
20
- "folders.manager.loading": "Lädt…",
21
- "folders.manager.newRoot": "Neuer Ordner",
22
- "folders.manager.add": "Anlegen",
23
- "folders.manager.addChild": "Unterordner",
24
- "folders.manager.rename": "Umbenennen",
25
- "folders.manager.delete": "Löschen",
26
- "folders.manager.save": "Speichern",
27
- "folders.manager.cancel": "Abbrechen",
28
- "folders.manager.working": "Speichert…",
29
- "folders.manager.deleteBlocked": "Erst Unterordner entfernen.",
30
- "folders.manager.deleteConfirmTitle": "Ordner löschen?",
31
- "folders.manager.deleteConfirmBody":
32
- "Der Ordner wird entfernt. Abgelegte Einträge wandern zurück zu „Ohne Ordner“.",
33
- },
34
9
  en: {
35
10
  "folders.section.createMode": "Save the entity first to pick a folder.",
36
11
  "folders.section.loading": "Loading…",
package/src/jobs/i18n.ts CHANGED
@@ -1,70 +1,64 @@
1
1
  // @runtime client
2
2
  // Server + client i18n for jobs operator screens.
3
3
 
4
- type LocalizedString = { readonly de: string; readonly en: string };
4
+ type LocalizedString = { readonly en: string };
5
5
 
6
6
  export const JOBS_I18N: Readonly<Record<string, LocalizedString>> = {
7
- "screen:job-runs.title": { de: "Job-Läufe", en: "Job runs" },
8
- "screen:job-run-detail.title": { de: "Job-Lauf", en: "Job run" },
9
- "jobs:nav.jobRuns": { de: "Jobs", en: "Jobs" },
10
- "jobs.runs.title": { de: "Job-Läufe", en: "Job runs" },
11
- "jobs.runs.loading": { de: "Lade Läufe…", en: "Loading runs…" },
12
- "jobs.runs.empty": { de: "Keine Job-Läufe.", en: "No job runs." },
13
- "jobs.runs.open": { de: "Details", en: "Details" },
14
- "jobs.runs.filter.status": { de: "Status", en: "Status" },
15
- "jobs.runs.filter.all": { de: "Alle", en: "All" },
16
- "jobs.runs.filter.completed": { de: "Abgeschlossen", en: "Completed" },
17
- "jobs.runs.filter.failed": { de: "Fehlgeschlagen", en: "Failed" },
18
- "jobs.runs.filter.running": { de: "Läuft", en: "Running" },
19
- "jobs.runs.filter.queued": { de: "Wartend", en: "Queued" },
20
- "jobs.runs.col.job": { de: "Job", en: "Job" },
21
- "jobs.runs.col.status": { de: "Status", en: "Status" },
22
- "jobs.runs.col.started": { de: "Gestartet", en: "Started" },
23
- "jobs.runs.col.duration": { de: "Dauer (ms)", en: "Duration (ms)" },
24
- "jobs.detail.loading": { de: "Lade Details…", en: "Loading details…" },
25
- "jobs.detail.missing": { de: "Lauf nicht gefunden.", en: "Run not found." },
26
- "jobs.detail.field.job": { de: "Job", en: "Job" },
27
- "jobs.detail.field.status": { de: "Status", en: "Status" },
28
- "jobs.detail.field.id": { de: "Run-ID", en: "Run ID" },
29
- "jobs.detail.field.started": { de: "Gestartet", en: "Started" },
30
- "jobs.detail.field.finished": { de: "Beendet", en: "Finished" },
31
- "jobs.detail.field.duration": { de: "Dauer (ms)", en: "Duration (ms)" },
32
- "jobs.detail.field.error": { de: "Fehler", en: "Error" },
33
- "jobs.detail.logs": { de: "Logs", en: "Logs" },
34
- "jobs.detail.logs.empty": { de: "Keine Log-Zeilen.", en: "No log lines." },
35
- "jobs.detail.retry": { de: "Erneut ausführen", en: "Retry" },
36
- "jobs.detail.retrying": { de: "Wird erneut gestartet…", en: "Retrying…" },
37
- "jobs.trigger.title": { de: "Job starten", en: "Run a job" },
7
+ "screen:job-runs.title": { en: "Job runs" },
8
+ "screen:job-run-detail.title": { en: "Job run" },
9
+ "jobs:nav.jobRuns": { en: "Jobs" },
10
+ "jobs.runs.title": { en: "Job runs" },
11
+ "jobs.runs.loading": { en: "Loading runs…" },
12
+ "jobs.runs.empty": { en: "No job runs." },
13
+ "jobs.runs.open": { en: "Details" },
14
+ "jobs.runs.filter.status": { en: "Status" },
15
+ "jobs.runs.filter.all": { en: "All" },
16
+ "jobs.runs.filter.completed": { en: "Completed" },
17
+ "jobs.runs.filter.failed": { en: "Failed" },
18
+ "jobs.runs.filter.running": { en: "Running" },
19
+ "jobs.runs.filter.queued": { en: "Queued" },
20
+ "jobs.runs.col.job": { en: "Job" },
21
+ "jobs.runs.col.status": { en: "Status" },
22
+ "jobs.runs.col.started": { en: "Started" },
23
+ "jobs.runs.col.duration": { en: "Duration (ms)" },
24
+ "jobs.detail.loading": { en: "Loading details…" },
25
+ "jobs.detail.missing": { en: "Run not found." },
26
+ "jobs.detail.field.job": { en: "Job" },
27
+ "jobs.detail.field.status": { en: "Status" },
28
+ "jobs.detail.field.id": { en: "Run ID" },
29
+ "jobs.detail.field.started": { en: "Started" },
30
+ "jobs.detail.field.finished": { en: "Finished" },
31
+ "jobs.detail.field.duration": { en: "Duration (ms)" },
32
+ "jobs.detail.field.error": { en: "Error" },
33
+ "jobs.detail.logs": { en: "Logs" },
34
+ "jobs.detail.logs.empty": { en: "No log lines." },
35
+ "jobs.detail.retry": { en: "Retry" },
36
+ "jobs.detail.retrying": { en: "Retrying…" },
37
+ "jobs.trigger.title": { en: "Run a job" },
38
38
  "jobs.trigger.explainer": {
39
- de: "Nur manuell startbare Jobs. Nach dem Start erscheint der Lauf in der Historie unten.",
40
39
  en: "Only manually triggerable jobs. After starting, the run appears in the history below.",
41
40
  },
42
- "jobs.trigger.job": { de: "Job", en: "Job" },
43
- "jobs.trigger.payload": { de: "Payload (JSON)", en: "Payload (JSON)" },
44
- "jobs.trigger.payload.hint": { de: "Schema-Hinweis", en: "Schema hint" },
41
+ "jobs.trigger.job": { en: "Job" },
42
+ "jobs.trigger.payload": { en: "Payload (JSON)" },
43
+ "jobs.trigger.payload.hint": { en: "Schema hint" },
45
44
  "jobs.trigger.payload.invalidJson": {
46
- de: "Payload ist kein gültiges JSON-Objekt.",
47
45
  en: "Payload is not a valid JSON object.",
48
46
  },
49
- "jobs.trigger.submit": { de: "Starten", en: "Run" },
50
- "jobs.trigger.submitting": { de: "Wird gestartet…", en: "Starting…" },
51
- "jobs.trigger.success": { de: "Job gestartet.", en: "Job started." },
47
+ "jobs.trigger.submit": { en: "Run" },
48
+ "jobs.trigger.submitting": { en: "Starting…" },
49
+ "jobs.trigger.success": { en: "Job started." },
52
50
  "jobs.trigger.empty": {
53
- de: "Keine manuell startbaren Jobs registriert.",
54
51
  en: "No manually triggerable jobs are registered.",
55
52
  },
56
53
  "jobs.trigger.perTenant": {
57
- de: "Läuft einmal pro aktivem Tenant.",
58
54
  en: "Runs once per active tenant.",
59
55
  },
60
- "jobs.errors.unknownJob": { de: "Unbekannter Job.", en: "Unknown job." },
56
+ "jobs.errors.unknownJob": { en: "Unknown job." },
61
57
  "jobs.errors.notManual": {
62
- de: "Dieser Job ist nicht manuell startbar.",
63
58
  en: "This job cannot be triggered manually.",
64
59
  },
65
- "jobs.errors.notFound": { de: "Nicht gefunden.", en: "Not found." },
60
+ "jobs.errors.notFound": { en: "Not found." },
66
61
  "jobs.errors.onlyFailedCanRetry": {
67
- de: "Nur fehlgeschlagene Läufe können erneut gestartet werden.",
68
62
  en: "Only failed runs can be retried.",
69
63
  },
70
64
  };
@@ -1,12 +1,8 @@
1
1
  // @runtime client
2
- import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
2
+ import {
3
+ type TranslationsByLocale,
4
+ translationsByLocaleFromKeys,
5
+ } from "@cosmicdrift/kumiko-renderer";
3
6
  import { JOBS_I18N } from "../i18n";
4
7
 
5
- const LOCALES = ["de", "en"] as const;
6
-
7
- export const defaultTranslations: TranslationsByLocale = Object.fromEntries(
8
- LOCALES.map((locale) => [
9
- locale,
10
- Object.fromEntries(Object.entries(JOBS_I18N).map(([key, value]) => [key, value[locale]])),
11
- ]),
12
- );
8
+ export const defaultTranslations: TranslationsByLocale = translationsByLocaleFromKeys(JOBS_I18N);
@@ -11,56 +11,52 @@
11
11
  // registriert. Die zwei customCss-Keys werden unconditional geliefert (schaden
12
12
  // bei allowCustomCss:false nicht, sind aber Pflicht für Consumer die es aktivieren).
13
13
 
14
- type LocalizedString = { readonly de: string; readonly en: string };
14
+ type LocalizedString = { readonly en: string };
15
15
 
16
16
  export const MANAGED_PAGES_I18N: Readonly<Record<string, LocalizedString>> = {
17
17
  // Screen-Titel (global/unpräfixiert — screenTitleKey = screen:<id>.title)
18
- "screen:page-list.title": { de: "Seiten", en: "Pages" },
19
- "screen:page-edit.title": { de: "Seite bearbeiten", en: "Edit page" },
20
- "screen:branding-settings.title": { de: "Branding", en: "Branding" },
18
+ "screen:page-list.title": { en: "Pages" },
19
+ "screen:page-edit.title": { en: "Edit page" },
20
+ "screen:branding-settings.title": { en: "Branding" },
21
21
 
22
22
  // Page-Entity Feld-Labels (managed-pages:entity:page:field:*)
23
- "managed-pages:entity:page:field:slug": { de: "Slug", en: "Slug" },
24
- "managed-pages:entity:page:field:lang": { de: "Sprache", en: "Language" },
25
- "managed-pages:entity:page:field:title": { de: "Titel", en: "Title" },
26
- "managed-pages:entity:page:field:published": { de: "Veröffentlicht", en: "Published" },
23
+ "managed-pages:entity:page:field:slug": { en: "Slug" },
24
+ "managed-pages:entity:page:field:lang": { en: "Language" },
25
+ "managed-pages:entity:page:field:title": { en: "Title" },
26
+ "managed-pages:entity:page:field:published": { en: "Published" },
27
27
  "managed-pages:entity:page:field:published:option:true": {
28
- de: "Veröffentlicht",
29
28
  en: "Published",
30
29
  },
31
- "managed-pages:entity:page:field:published:option:false": { de: "Entwurf", en: "Draft" },
32
- "managed-pages:entity:page:field:description": { de: "Beschreibung", en: "Description" },
33
- "managed-pages:entity:page:field:ogImage": { de: "OG-Bild", en: "OG image" },
34
- "managed-pages:entity:page:field:body": { de: "Inhalt", en: "Content" },
30
+ "managed-pages:entity:page:field:published:option:false": { en: "Draft" },
31
+ "managed-pages:entity:page:field:description": { en: "Description" },
32
+ "managed-pages:entity:page:field:ogImage": { en: "OG image" },
33
+ "managed-pages:entity:page:field:body": { en: "Content" },
35
34
 
36
35
  // Config-Edit Feld-Labels (managed-pages:entity:__config-edit__:field:*, camelCase Form-Keys)
37
- "managed-pages:entity:__config-edit__:field:title": { de: "Website-Titel", en: "Site title" },
36
+ "managed-pages:entity:__config-edit__:field:title": { en: "Site title" },
38
37
  "managed-pages:entity:__config-edit__:field:description": {
39
- de: "Beschreibung",
40
38
  en: "Description",
41
39
  },
42
- "managed-pages:entity:__config-edit__:field:siteUrl": { de: "Website-URL", en: "Site URL" },
40
+ "managed-pages:entity:__config-edit__:field:siteUrl": { en: "Site URL" },
43
41
  "managed-pages:entity:__config-edit__:field:accentColor": {
44
- de: "Akzentfarbe",
45
42
  en: "Accent color",
46
43
  },
47
- "managed-pages:entity:__config-edit__:field:logoUrl": { de: "Logo-URL", en: "Logo URL" },
48
- "managed-pages:entity:__config-edit__:field:layoutPreset": { de: "Layout", en: "Layout" },
44
+ "managed-pages:entity:__config-edit__:field:logoUrl": { en: "Logo URL" },
45
+ "managed-pages:entity:__config-edit__:field:layoutPreset": { en: "Layout" },
49
46
 
50
47
  // Section-Header
51
- "managed-pages:section.meta": { de: "Metadaten", en: "Metadata" },
52
- "managed-pages:section.body": { de: "Inhalt", en: "Content" },
53
- "managed-pages:branding.section.identity": { de: "Identität", en: "Identity" },
48
+ "managed-pages:section.meta": { en: "Metadata" },
49
+ "managed-pages:section.body": { en: "Content" },
50
+ "managed-pages:branding.section.identity": { en: "Identity" },
54
51
 
55
52
  // Row-Actions + Confirm (pageListScreen)
56
- "managed-pages:actions.edit": { de: "Bearbeiten", en: "Edit" },
57
- "managed-pages:actions.delete": { de: "Löschen", en: "Delete" },
53
+ "managed-pages:actions.edit": { en: "Edit" },
54
+ "managed-pages:actions.delete": { en: "Delete" },
58
55
  "managed-pages:confirms.page-delete": {
59
- de: "Diese Seite wirklich löschen?",
60
56
  en: "Delete this page?",
61
57
  },
62
58
 
63
59
  // Nur bei allowCustomCss:true im Screen — unconditional geliefert
64
- "managed-pages:entity:__config-edit__:field:customCss": { de: "Eigenes CSS", en: "Custom CSS" },
65
- "managed-pages:branding.section.custom-css": { de: "Eigenes CSS", en: "Custom CSS" },
60
+ "managed-pages:entity:__config-edit__:field:customCss": { en: "Custom CSS" },
61
+ "managed-pages:branding.section.custom-css": { en: "Custom CSS" },
66
62
  };
@@ -9,16 +9,11 @@
9
9
  // Server-Form) in die locale-first TranslationsByLocale-Form die der Client
10
10
  // erwartet — kein Key-Duplikat, kein Drift.
11
11
 
12
- import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
12
+ import {
13
+ type TranslationsByLocale,
14
+ translationsByLocaleFromKeys,
15
+ } from "@cosmicdrift/kumiko-renderer";
13
16
  import { MANAGED_PAGES_I18N } from "../i18n";
14
17
 
15
- const LOCALES = ["de", "en"] as const;
16
-
17
- export const defaultTranslations: TranslationsByLocale = Object.fromEntries(
18
- LOCALES.map((locale) => [
19
- locale,
20
- Object.fromEntries(
21
- Object.entries(MANAGED_PAGES_I18N).map(([key, value]) => [key, value[locale]]),
22
- ),
23
- ]),
24
- );
18
+ export const defaultTranslations: TranslationsByLocale =
19
+ translationsByLocaleFromKeys(MANAGED_PAGES_I18N);
@@ -1,3 +1,3 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const NOTES_HISTORY_FEATURE_I18N: Readonly<Record<string, LocalizedString>> = {};
@@ -1,20 +1,12 @@
1
1
  // @runtime client
2
2
  // Default translation bundle for the notes-history UI. notesHistoryClient()
3
3
  // hangs it into the LocaleProvider as a fallback bundle — apps override
4
- // individual keys via notesHistoryClient({ translations: { de: { ... } } }).
4
+ // individual keys via notesHistoryClient({ translations }).
5
5
  // Keys follow `notesHistory.<area>.<slug>`.
6
6
 
7
7
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
8
8
 
9
9
  export const defaultTranslations: TranslationsByLocale = {
10
- de: {
11
- "notesHistory.section.createMode": "Speichere zuerst den Eintrag, um Notizen anzulegen.",
12
- "notesHistory.section.loading": "Lädt…",
13
- "notesHistory.section.empty": "Noch keine Notizen.",
14
- "notesHistory.section.working": "Speichert…",
15
- "notesHistory.section.add": "Notiz hinzufügen",
16
- "notesHistory.section.meta": "{author} · {date}",
17
- },
18
10
  en: {
19
11
  "notesHistory.section.createMode": "Save the entity first to add notes.",
20
12
  "notesHistory.section.loading": "Loading…",
@@ -1,5 +1,5 @@
1
- type LocalizedString = { readonly de: string; readonly en: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const PAT_FEATURE_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:api-tokens.title": { de: "Personal Access Tokens", en: "Personal Access Tokens" },
4
+ "screen:api-tokens.title": { en: "Personal Access Tokens" },
5
5
  };
@@ -2,43 +2,6 @@
2
2
  import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
3
3
 
4
4
  export const defaultTranslations: TranslationsByLocale = {
5
- de: {
6
- "pat.title": "Personal Access Tokens",
7
- "pat.create.title": "Neuen Token erstellen",
8
- "pat.create.subtitle":
9
- "Wähle Berechtigungen und eine Gültigkeit. Der Token wird nur einmal angezeigt.",
10
- "pat.create.name": "Name",
11
- "pat.create.namePlaceholder": "z. B. CLI-Automatisierung",
12
- "pat.create.scopes": "Zugriff pro Bereich",
13
- "pat.level.none": "Kein Zugriff",
14
- "pat.level.read": "Lesen",
15
- "pat.level.write": "Lesen & Schreiben",
16
- "pat.create.expiry": "Gültig bis",
17
- "pat.create.submit": "Token erstellen",
18
- "pat.create.needName": "Bitte einen Namen vergeben.",
19
- "pat.create.needScope": "Bitte mindestens eine Berechtigung wählen.",
20
- "pat.create.needPassword": "Bitte dein Passwort zur Bestätigung eingeben.",
21
- "pat.create.currentPassword": "Passwort (zur Bestätigung)",
22
- "pat.create.mfaCode": "2FA-Code (falls aktiviert)",
23
- "pat.create.mfaCodePlaceholder": "6-stelliger Code",
24
- "pat.expiry.30d": "30 Tage",
25
- "pat.expiry.90d": "90 Tage",
26
- "pat.expiry.1y": "1 Jahr",
27
- "pat.expiry.never": "Unbegrenzt",
28
- "pat.created.hint":
29
- "Kopiere diesen Token jetzt — er wird aus Sicherheitsgründen nur dieses eine Mal angezeigt.",
30
- "pat.created.copy": "Kopieren",
31
- "pat.created.copied": "Kopiert ✓",
32
- "pat.created.dismiss": "Fertig",
33
- "pat.list.title": "Deine Tokens",
34
- "pat.list.empty": "Noch keine Tokens.",
35
- "pat.list.revoke": "Widerrufen",
36
- "pat.list.revoked": "Widerrufen",
37
- "pat.list.validUntil": "Gültig bis {date}",
38
- "pat.list.neverExpires": "Unbegrenzt gültig",
39
- "pat.list.created": "Erstellt {date}",
40
- "pat.error.generic": "Aktion fehlgeschlagen.",
41
- },
42
5
  en: {
43
6
  "pat.title": "Personal Access Tokens",
44
7
  "pat.create.title": "Create a new token",