@cosmicdrift/kumiko-bundled-features 0.207.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 -39
  4. package/src/admin-shell/web/i18n.ts +6 -11
  5. package/src/audit/i18n.ts +25 -41
  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 -265
  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 -3
  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 -126
  28. package/src/cap-counter/i18n.ts +5 -11
  29. package/src/compliance-profiles/i18n.ts +3 -11
  30. package/src/compliance-profiles/web/i18n.ts +0 -20
  31. package/src/config/i18n.ts +5 -5
  32. package/src/config/web/i18n.ts +1 -19
  33. package/src/custom-fields/web/i18n.ts +1 -18
  34. package/src/delivery/i18n.ts +3 -7
  35. package/src/delivery/web/i18n.ts +0 -20
  36. package/src/feature-toggles/i18n.ts +3 -11
  37. package/src/feature-toggles/web/i18n.ts +0 -24
  38. package/src/folders/web/i18n.ts +1 -51
  39. package/src/jobs/i18n.ts +40 -68
  40. package/src/jobs/web/i18n.ts +5 -9
  41. package/src/managed-pages/i18n.ts +23 -67
  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 -17
  45. package/src/personal-access-tokens/i18n.ts +2 -6
  46. package/src/personal-access-tokens/web/i18n.ts +0 -72
  47. package/src/sessions/i18n.ts +17 -21
  48. package/src/tags/i18n.ts +2 -2
  49. package/src/tags/web/i18n.ts +1 -52
  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 -28
  53. package/src/tenant/__tests__/members-screens.boot.test.ts +0 -2
  54. package/src/tenant/i18n.ts +13 -27
  55. package/src/tenant/web/i18n.ts +0 -38
  56. package/src/tier-engine/i18n.ts +3 -39
  57. package/src/user/i18n.ts +14 -32
  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 -70
  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 -157
  68. package/src/user-profile/i18n.ts +1 -71
@@ -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",
@@ -131,69 +68,6 @@ export const defaultTranslations: TranslationsByLocale = {
131
68
  "auth.mfa.regenerate.acknowledge": "I've saved my new recovery codes.",
132
69
  "auth.mfa.regenerate.done": "Done",
133
70
  },
134
- es: {
135
- "screen:auth-mfa-enable.title": "Verificación en dos pasos",
136
- "auth.mfa.verify.title": "Verificación en dos pasos",
137
- "auth.mfa.verify.subtitle": "Introduce el código de 6 dígitos de tu app de autenticación.",
138
- "auth.mfa.verify.code": "Código",
139
- "auth.mfa.verify.submit": "Confirmar",
140
- "auth.mfa.verify.submitting": "…",
141
- "auth.mfa.verify.backToLogin": "Volver al inicio de sesión",
142
- "auth.mfa.errors.invalidCode": "Código no válido. Inténtalo de nuevo.",
143
- "auth.mfa.errors.invalidTotpCode": "Código no válido. Inténtalo de nuevo.",
144
- "auth.mfa.errors.invalidChallengeToken":
145
- "Tu inicio de sesión ha caducado. Vuelve a iniciar sesión.",
146
- "auth.mfa.errors.challengeExpired": "Tu inicio de sesión ha caducado. Vuelve a iniciar sesión.",
147
- "auth.mfa.errors.tooManyAttempts": "Demasiados intentos fallidos. Vuelve a iniciar sesión.",
148
- "auth.mfa.errors.tooManyAttemptsWithSeconds":
149
- "Demasiados intentos fallidos. Inténtalo de nuevo en {seconds} segundos o vuelve a iniciar sesión.",
150
- "auth.mfa.errors.verifyFailed": "Error al confirmar.",
151
- "auth.mfa.errors.mfaAlreadyEnabled": "La verificación en dos pasos ya está activada.",
152
- "auth.mfa.errors.mfaNotEnabled": "La verificación en dos pasos no está activada.",
153
- "auth.mfa.errors.invalidSetupToken": "La configuración ha caducado. Vuelve a empezar.",
154
- "auth.mfa.errors.setupFailed": "Error al configurar. Inténtalo de nuevo.",
155
- "auth.mfa.errors.invalidRecoveryCode": "Código de recuperación no válido.",
156
- "auth.mfa.enable.title": "Verificación en dos pasos",
157
- "auth.mfa.enable.intro":
158
- "Protege tu cuenta con una capa adicional usando una app de autenticación (p. ej. Google Authenticator, 1Password).",
159
- "auth.mfa.enable.start": "Iniciar configuración",
160
- "auth.mfa.enable.scanTitle": "Escanea el código QR",
161
- "auth.mfa.enable.manualEntry": "O introdúcelo manualmente:",
162
- "auth.mfa.enable.recoveryTitle": "Códigos de recuperación",
163
- "auth.mfa.enable.recoveryHint":
164
- "Guarda estos códigos en un lugar seguro. Solo se muestran esta vez y te permiten entrar si pierdes tu dispositivo.",
165
- "auth.mfa.enable.acknowledge": "He guardado mis códigos de recuperación.",
166
- "auth.mfa.enable.code": "Código de la app de autenticación",
167
- "auth.mfa.enable.cancel": "Cancelar",
168
- "auth.mfa.enable.confirm": "Activar",
169
- "auth.mfa.enable.success": "Ya tienes activada la verificación en dos pasos.",
170
- "auth.mfa.setup.title": "Se requiere verificación en dos pasos",
171
- "auth.mfa.setup.subtitle":
172
- "Tu cuenta requiere verificación en dos pasos. Configúrala ahora para iniciar sesión.",
173
- "auth.mfa.setup.intro":
174
- "Escanea el código QR con una app de autenticación (p. ej. Google Authenticator, 1Password).",
175
- "auth.mfa.setup.start": "Iniciar configuración",
176
- "auth.mfa.setup.confirm": "Completar configuración",
177
- "auth.mfa.disable.title": "Desactivar la verificación en dos pasos",
178
- "auth.mfa.disable.description":
179
- "Confirma con un código de tu app de autenticación o un código de recuperación. Después, tu cuenta solo estará protegida por tu contraseña.",
180
- "auth.mfa.disable.code": "Código de la app de autenticación o código de recuperación",
181
- "auth.mfa.disable.confirm": "Desactivar",
182
- "auth.mfa.disable.cancel": "Cancelar",
183
- "auth.mfa.disable.trigger": "Desactivar la verificación en dos pasos",
184
- "auth.mfa.regenerate.title": "Generar nuevos códigos de recuperación",
185
- "auth.mfa.regenerate.description":
186
- "Confirma con un código de tu app de autenticación. Todos los códigos de recuperación anteriores dejarán de funcionar de inmediato.",
187
- "auth.mfa.regenerate.code": "Código de la app de autenticación",
188
- "auth.mfa.regenerate.confirm": "Generar de nuevo",
189
- "auth.mfa.regenerate.cancel": "Cancelar",
190
- "auth.mfa.regenerate.trigger": "Generar nuevos códigos de recuperación",
191
- "auth.mfa.regenerate.newCodesTitle": "Tus nuevos códigos de recuperación",
192
- "auth.mfa.regenerate.newCodesHint":
193
- "Guarda estos códigos en un lugar seguro. Los códigos antiguos dejan de funcionar de inmediato.",
194
- "auth.mfa.regenerate.acknowledge": "He guardado mis nuevos códigos de recuperación.",
195
- "auth.mfa.regenerate.done": "Listo",
196
- },
197
71
  };
198
72
 
199
73
  export { mergeTranslations } from "@cosmicdrift/kumiko-renderer";
@@ -1,17 +1,11 @@
1
- type LocalizedString = { readonly de: string; readonly en: string; readonly es: 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", es: "Límites de uso" },
5
- "cap-counter:entity:cap-counter:field:capName": { de: "Limit", en: "Cap", es: "Límite" },
6
- "cap-counter:entity:cap-counter:field:value": { de: "Wert", en: "Value", es: "Valor" },
7
- "cap-counter:entity:cap-counter:field:periodStart": {
8
- de: "Periodenstart",
9
- en: "Period start",
10
- es: "Inicio del período",
11
- },
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" },
12
8
  "cap-counter:entity:cap-counter:field:lastSoftWarnedAt": {
13
- de: "Letzte Soft-Warnung",
14
9
  en: "Last soft warning",
15
- es: "Última advertencia suave",
16
10
  },
17
11
  };
@@ -1,14 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string; readonly es: 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": {
5
- de: "Compliance-Profil",
6
- en: "Compliance profile",
7
- es: "Perfil de cumplimiento",
8
- },
9
- "compliance-profiles:nav.profilePicker": {
10
- de: "Compliance",
11
- en: "Compliance",
12
- es: "Cumplimiento",
13
- },
4
+ "screen:profile-picker.title": { en: "Compliance profile" },
5
+ "compliance-profiles:nav.profilePicker": { en: "Compliance" },
14
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…",
@@ -22,14 +12,4 @@ export const defaultTranslations: TranslationsByLocale = {
22
12
  "compliance.profile.catalog": "Available profiles",
23
13
  "compliance-profiles:nav.profilePicker": "Compliance",
24
14
  },
25
- es: {
26
- "compliance.profile.title": "Perfil de cumplimiento",
27
- "compliance.profile.loading": "Cargando perfiles de cumplimiento…",
28
- "compliance.profile.current": "Actual",
29
- "compliance.profile.select": "Perfil",
30
- "compliance.profile.save": "Guardar perfil",
31
- "compliance.profile.saving": "Guardando…",
32
- "compliance.profile.catalog": "Perfiles disponibles",
33
- "compliance-profiles:nav.profilePicker": "Cumplimiento",
34
- },
35
15
  };
@@ -1,9 +1,9 @@
1
- type LocalizedString = { readonly de: string; readonly en: string; readonly es: 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", es: "Ajustes" },
6
- "config.settings.system": { de: "Plattform", en: "Platform", es: "Plataforma" },
7
- "config.settings.tenant": { de: "Organisation", en: "Organization", es: "Organización" },
8
- "config.settings.user": { de: "Persönlich", en: "Personal", es: "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",
@@ -28,13 +19,4 @@ export const defaultTranslations: TranslationsByLocale = {
28
19
  "config.errors.invalidScope": "This scope is not allowed for this key.",
29
20
  "config.errors.unknownKey": "Unknown configuration key.",
30
21
  },
31
- es: {
32
- "config.settings.title": "Ajustes",
33
- "config.settings.system": "Plataforma",
34
- "config.settings.tenant": "Organización",
35
- "config.settings.user": "Personal",
36
- "config.errors.systemOnly": "Este valor solo puede establecerlo el sistema.",
37
- "config.errors.invalidScope": "Este nivel no está permitido para esta clave.",
38
- "config.errors.unknownKey": "Clave de configuración desconocida.",
39
- },
40
22
  };
@@ -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…",
@@ -27,13 +19,4 @@ export const defaultTranslations: TranslationsByLocale = {
27
19
  "custom-fields.form.saving": "Saving…",
28
20
  "custom-fields.errors.saveFailed": "Save failed.",
29
21
  },
30
- es: {
31
- "custom-fields.form.createMode":
32
- "Guarda primero la entrada para poder definir los campos personalizados.",
33
- "custom-fields.form.loading": "Cargando…",
34
- "custom-fields.form.empty": 'No hay campos personalizados definidos para "{entityName}".',
35
- "custom-fields.form.save": "Guardar campos personalizados",
36
- "custom-fields.form.saving": "Guardando…",
37
- "custom-fields.errors.saveFailed": "Error al guardar.",
38
- },
39
22
  };
@@ -1,10 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string; readonly es: string };
1
+ type LocalizedString = { readonly en: string };
2
2
 
3
3
  export const DELIVERY_I18N: Readonly<Record<string, LocalizedString>> = {
4
- "screen:delivery-log.title": {
5
- de: "Delivery-Log",
6
- en: "Delivery log",
7
- es: "Registro de entregas",
8
- },
9
- "delivery:nav.deliveryLog": { de: "Zustellungen", en: "Delivery", es: "Entregas" },
4
+ "screen:delivery-log.title": { en: "Delivery log" },
5
+ "delivery:nav.deliveryLog": { en: "Delivery" },
10
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…",
@@ -22,14 +12,4 @@ export const defaultTranslations: TranslationsByLocale = {
22
12
  "delivery.log.col.status": "Status",
23
13
  "delivery:nav.deliveryLog": "Delivery",
24
14
  },
25
- es: {
26
- "delivery.log.title": "Registro de entregas",
27
- "delivery.log.loading": "Cargando intentos de entrega…",
28
- "delivery.log.empty": "No hay intentos de entrega.",
29
- "delivery.log.col.type": "Tipo",
30
- "delivery.log.col.channel": "Canal",
31
- "delivery.log.col.recipient": "Destinatario",
32
- "delivery.log.col.status": "Estado",
33
- "delivery:nav.deliveryLog": "Entregas",
34
- },
35
15
  };
@@ -1,14 +1,6 @@
1
- type LocalizedString = { readonly de: string; readonly en: string; readonly es: 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": {
5
- de: "Feature-Toggles",
6
- en: "Feature toggles",
7
- es: "Feature toggles",
8
- },
9
- "feature-toggles:nav.toggleAdmin": {
10
- de: "Feature-Toggles",
11
- en: "Feature toggles",
12
- es: "Feature toggles",
13
- },
4
+ "screen:toggle-admin.title": { en: "Feature toggles" },
5
+ "feature-toggles:nav.toggleAdmin": { en: "Feature toggles" },
14
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…",
@@ -26,16 +14,4 @@ export const defaultTranslations: TranslationsByLocale = {
26
14
  "feature-toggles.admin.alwaysOn": "always on",
27
15
  "feature-toggles:nav.toggleAdmin": "Feature toggles",
28
16
  },
29
- es: {
30
- "feature-toggles.admin.title": "Feature toggles",
31
- "feature-toggles.admin.loading": "Cargando Feature toggles…",
32
- "feature-toggles.admin.col.feature": "Función",
33
- "feature-toggles.admin.col.default": "Default",
34
- "feature-toggles.admin.col.override": "Override",
35
- "feature-toggles.admin.col.effective": "Efectivo",
36
- "feature-toggles.admin.toggle": "Alternar",
37
- "feature-toggles.admin.saving": "Guardando…",
38
- "feature-toggles.admin.alwaysOn": "siempre activado",
39
- "feature-toggles:nav.toggleAdmin": "Feature toggles",
40
- },
41
17
  };
@@ -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…",
@@ -56,29 +31,4 @@ export const defaultTranslations: TranslationsByLocale = {
56
31
  "folders.manager.deleteConfirmBody":
57
32
  "The folder will be removed. Filed entries move back to Unfiled.",
58
33
  },
59
- es: {
60
- "folders.section.createMode": "Guarda primero la entrada para elegir una carpeta.",
61
- "folders.section.loading": "Cargando…",
62
- "folders.section.label": "Carpeta",
63
- "folders.section.placeholder": "Selecciona una carpeta…",
64
- "folders.section.empty": "No se encontraron carpetas.",
65
- "folders.section.none": "— Sin carpeta —",
66
- "folders.section.newLabel": "Nueva carpeta",
67
- "folders.section.create": "Crear carpeta y archivar",
68
- "folders.section.working": "Guardando…",
69
-
70
- "folders.manager.loading": "Cargando…",
71
- "folders.manager.newRoot": "Nueva carpeta",
72
- "folders.manager.add": "Crear",
73
- "folders.manager.addChild": "Subcarpeta",
74
- "folders.manager.rename": "Renombrar",
75
- "folders.manager.delete": "Eliminar",
76
- "folders.manager.save": "Guardar",
77
- "folders.manager.cancel": "Cancelar",
78
- "folders.manager.working": "Guardando…",
79
- "folders.manager.deleteBlocked": "Elimina antes las subcarpetas.",
80
- "folders.manager.deleteConfirmTitle": "¿Eliminar la carpeta?",
81
- "folders.manager.deleteConfirmBody":
82
- "La carpeta se eliminará. Las entradas archivadas volverán a Sin archivar.",
83
- },
84
34
  };
package/src/jobs/i18n.ts CHANGED
@@ -1,92 +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; readonly es: 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", es: "Ejecuciones de trabajos" },
8
- "screen:job-run-detail.title": { de: "Job-Lauf", en: "Job run", es: "Ejecución de trabajo" },
9
- "jobs:nav.jobRuns": { de: "Jobs", en: "Jobs", es: "Trabajos" },
10
- "jobs.runs.title": { de: "Job-Läufe", en: "Job runs", es: "Ejecuciones de trabajos" },
11
- "jobs.runs.loading": { de: "Lade Läufe…", en: "Loading runs…", es: "Cargando ejecuciones…" },
12
- "jobs.runs.empty": {
13
- de: "Keine Job-Läufe.",
14
- en: "No job runs.",
15
- es: "No hay ejecuciones de trabajos.",
16
- },
17
- "jobs.runs.open": { de: "Details", en: "Details", es: "Detalles" },
18
- "jobs.runs.filter.status": { de: "Status", en: "Status", es: "Estado" },
19
- "jobs.runs.filter.all": { de: "Alle", en: "All", es: "Todos" },
20
- "jobs.runs.filter.completed": { de: "Abgeschlossen", en: "Completed", es: "Completado" },
21
- "jobs.runs.filter.failed": { de: "Fehlgeschlagen", en: "Failed", es: "Fallido" },
22
- "jobs.runs.filter.running": { de: "Läuft", en: "Running", es: "En curso" },
23
- "jobs.runs.filter.queued": { de: "Wartend", en: "Queued", es: "En cola" },
24
- "jobs.runs.col.job": { de: "Job", en: "Job", es: "Trabajo" },
25
- "jobs.runs.col.status": { de: "Status", en: "Status", es: "Estado" },
26
- "jobs.runs.col.started": { de: "Gestartet", en: "Started", es: "Iniciado" },
27
- "jobs.runs.col.duration": { de: "Dauer (ms)", en: "Duration (ms)", es: "Duración (ms)" },
28
- "jobs.detail.loading": { de: "Lade Details…", en: "Loading details…", es: "Cargando detalles…" },
29
- "jobs.detail.missing": {
30
- de: "Lauf nicht gefunden.",
31
- en: "Run not found.",
32
- es: "Ejecución no encontrada.",
33
- },
34
- "jobs.detail.field.job": { de: "Job", en: "Job", es: "Trabajo" },
35
- "jobs.detail.field.status": { de: "Status", en: "Status", es: "Estado" },
36
- "jobs.detail.field.id": { de: "Run-ID", en: "Run ID", es: "ID de ejecución" },
37
- "jobs.detail.field.started": { de: "Gestartet", en: "Started", es: "Iniciado" },
38
- "jobs.detail.field.finished": { de: "Beendet", en: "Finished", es: "Finalizado" },
39
- "jobs.detail.field.duration": { de: "Dauer (ms)", en: "Duration (ms)", es: "Duración (ms)" },
40
- "jobs.detail.field.error": { de: "Fehler", en: "Error", es: "Error" },
41
- "jobs.detail.logs": { de: "Logs", en: "Logs", es: "Registros" },
42
- "jobs.detail.logs.empty": {
43
- de: "Keine Log-Zeilen.",
44
- en: "No log lines.",
45
- es: "No hay líneas de registro.",
46
- },
47
- "jobs.detail.retry": { de: "Erneut ausführen", en: "Retry", es: "Reintentar" },
48
- "jobs.detail.retrying": { de: "Wird erneut gestartet…", en: "Retrying…", es: "Reintentando…" },
49
- "jobs.trigger.title": { de: "Job starten", en: "Run a job", es: "Ejecutar un trabajo" },
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" },
50
38
  "jobs.trigger.explainer": {
51
- de: "Nur manuell startbare Jobs. Nach dem Start erscheint der Lauf in der Historie unten.",
52
39
  en: "Only manually triggerable jobs. After starting, the run appears in the history below.",
53
- es: "Solo trabajos que se pueden iniciar manualmente. Tras iniciarlo, la ejecución aparece en el historial de abajo.",
54
40
  },
55
- "jobs.trigger.job": { de: "Job", en: "Job", es: "Trabajo" },
56
- "jobs.trigger.payload": { de: "Payload (JSON)", en: "Payload (JSON)", es: "Payload (JSON)" },
57
- "jobs.trigger.payload.hint": { de: "Schema-Hinweis", en: "Schema hint", es: "Pista de esquema" },
41
+ "jobs.trigger.job": { en: "Job" },
42
+ "jobs.trigger.payload": { en: "Payload (JSON)" },
43
+ "jobs.trigger.payload.hint": { en: "Schema hint" },
58
44
  "jobs.trigger.payload.invalidJson": {
59
- de: "Payload ist kein gültiges JSON-Objekt.",
60
45
  en: "Payload is not a valid JSON object.",
61
- es: "El payload no es un objeto JSON válido.",
62
46
  },
63
- "jobs.trigger.submit": { de: "Starten", en: "Run", es: "Ejecutar" },
64
- "jobs.trigger.submitting": { de: "Wird gestartet…", en: "Starting…", es: "Iniciando…" },
65
- "jobs.trigger.success": { de: "Job gestartet.", en: "Job started.", es: "Trabajo iniciado." },
47
+ "jobs.trigger.submit": { en: "Run" },
48
+ "jobs.trigger.submitting": { en: "Starting…" },
49
+ "jobs.trigger.success": { en: "Job started." },
66
50
  "jobs.trigger.empty": {
67
- de: "Keine manuell startbaren Jobs registriert.",
68
51
  en: "No manually triggerable jobs are registered.",
69
- es: "No hay trabajos registrados que se puedan iniciar manualmente.",
70
52
  },
71
53
  "jobs.trigger.perTenant": {
72
- de: "Läuft einmal pro aktivem Tenant.",
73
54
  en: "Runs once per active tenant.",
74
- es: "Se ejecuta una vez por cada organización activa.",
75
- },
76
- "jobs.errors.unknownJob": {
77
- de: "Unbekannter Job.",
78
- en: "Unknown job.",
79
- es: "Trabajo desconocido.",
80
55
  },
56
+ "jobs.errors.unknownJob": { en: "Unknown job." },
81
57
  "jobs.errors.notManual": {
82
- de: "Dieser Job ist nicht manuell startbar.",
83
58
  en: "This job cannot be triggered manually.",
84
- es: "Este trabajo no se puede iniciar manualmente.",
85
59
  },
86
- "jobs.errors.notFound": { de: "Nicht gefunden.", en: "Not found.", es: "No encontrado." },
60
+ "jobs.errors.notFound": { en: "Not found." },
87
61
  "jobs.errors.onlyFailedCanRetry": {
88
- de: "Nur fehlgeschlagene Läufe können erneut gestartet werden.",
89
62
  en: "Only failed runs can be retried.",
90
- es: "Solo se pueden reintentar las ejecuciones fallidas.",
91
63
  },
92
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", "es"] 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);