@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.
- package/package.json +9 -8
- package/src/admin-shell/__tests__/admin-shell.boot.test.ts +1 -1
- package/src/admin-shell/i18n.ts +17 -20
- package/src/admin-shell/web/i18n.ts +6 -11
- package/src/audit/i18n.ts +25 -25
- package/src/audit/web/i18n.ts +5 -9
- package/src/auth-email-password/__tests__/email-templates.test.ts +4 -0
- package/src/auth-email-password/email-templates.ts +97 -149
- package/src/auth-email-password/i18n.ts +6 -136
- package/src/auth-email-password/web/__tests__/confirm-account-unlock-screen.test.tsx +7 -7
- package/src/auth-email-password/web/__tests__/forgot-password-screen.test.tsx +14 -14
- package/src/auth-email-password/web/__tests__/invite-accept-screen.test.tsx +23 -25
- package/src/auth-email-password/web/__tests__/login-screen.test.tsx +60 -68
- package/src/auth-email-password/web/__tests__/request-account-unlock-screen.test.tsx +24 -24
- package/src/auth-email-password/web/__tests__/reset-password-screen.test.tsx +20 -20
- package/src/auth-email-password/web/__tests__/signup-complete-screen.test.tsx +9 -9
- package/src/auth-email-password/web/__tests__/signup-screen.test.tsx +11 -11
- package/src/auth-email-password/web/__tests__/test-utils.tsx +2 -2
- package/src/auth-email-password/web/__tests__/user-menu.test.tsx +3 -3
- package/src/auth-email-password/web/__tests__/verify-email-screen.test.tsx +3 -3
- package/src/auth-email-password/web/invite-accept-screen.tsx +3 -1
- package/src/auth-mfa/__tests__/errors-i18n-parity.test.ts +2 -4
- package/src/auth-mfa/i18n.ts +1 -2
- package/src/auth-mfa/web/__tests__/mfa-enable-screen.test.tsx +15 -15
- package/src/auth-mfa/web/__tests__/mfa-setup-preauth-screen.test.tsx +45 -49
- package/src/auth-mfa/web/__tests__/mfa-verify-screen.test.tsx +10 -10
- package/src/auth-mfa/web/i18n.ts +0 -63
- package/src/cap-counter/i18n.ts +5 -6
- package/src/compliance-profiles/i18n.ts +3 -3
- package/src/compliance-profiles/web/i18n.ts +0 -10
- package/src/config/i18n.ts +5 -5
- package/src/config/web/i18n.ts +1 -10
- package/src/custom-fields/web/i18n.ts +1 -9
- package/src/delivery/i18n.ts +3 -3
- package/src/delivery/web/i18n.ts +0 -10
- package/src/feature-toggles/i18n.ts +3 -3
- package/src/feature-toggles/web/i18n.ts +0 -12
- package/src/folders/web/i18n.ts +1 -26
- package/src/jobs/i18n.ts +40 -46
- package/src/jobs/web/i18n.ts +5 -9
- package/src/managed-pages/i18n.ts +23 -27
- package/src/managed-pages/web/i18n.ts +6 -11
- package/src/notes-history/i18n.ts +1 -1
- package/src/notes-history/web/i18n.ts +1 -9
- package/src/personal-access-tokens/i18n.ts +2 -2
- package/src/personal-access-tokens/web/i18n.ts +0 -37
- package/src/sessions/i18n.ts +17 -17
- package/src/tags/i18n.ts +2 -2
- package/src/tags/web/i18n.ts +1 -27
- package/src/template-resolver/web/__tests__/client-plugin.test.tsx +2 -2
- package/src/template-resolver/web/__tests__/editor-read-only.test.tsx +5 -5
- package/src/template-resolver/web/i18n.ts +0 -14
- package/src/tenant/__tests__/members-screens.boot.test.ts +0 -2
- package/src/tenant/i18n.ts +13 -16
- package/src/tenant/web/i18n.ts +0 -19
- package/src/tier-engine/i18n.ts +3 -19
- package/src/user/i18n.ts +14 -15
- package/src/user-data-rights/__tests__/default-mailers.test.ts +4 -0
- package/src/user-data-rights/__tests__/email-templates.test.ts +4 -0
- package/src/user-data-rights/__tests__/mail-default-bridge.integration.test.ts +2 -0
- package/src/user-data-rights/__tests__/run-export-jobs-cron-context.integration.test.ts +4 -0
- package/src/user-data-rights/email-templates.ts +55 -91
- package/src/user-data-rights/i18n.ts +18 -22
- package/src/user-data-rights/lib/default-mailers.ts +4 -1
- package/src/user-data-rights/web/__tests__/deletion-screens.test.tsx +11 -11
- package/src/user-data-rights/web/__tests__/public-deletion-gate.test.tsx +5 -5
- package/src/user-data-rights/web/i18n.ts +9 -88
- package/src/user-profile/i18n.ts +1 -36
package/src/sessions/i18n.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
// @runtime client
|
|
2
2
|
// Server + client i18n for the sessions operator screens.
|
|
3
3
|
|
|
4
|
-
type LocalizedString = { readonly
|
|
4
|
+
type LocalizedString = { readonly en: string };
|
|
5
5
|
|
|
6
6
|
export const SESSIONS_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
7
|
-
"screen:session-list.title": {
|
|
8
|
-
"screen:session-detail.title": {
|
|
9
|
-
"sessions:nav.sessionList": {
|
|
10
|
-
"sessions.list.col.id": {
|
|
11
|
-
"sessions.list.col.userId": {
|
|
12
|
-
"sessions.list.col.createdAt": {
|
|
13
|
-
"sessions.list.col.expiresAt": {
|
|
14
|
-
"sessions.list.col.revokedAt": {
|
|
15
|
-
"sessions.list.action.open": {
|
|
16
|
-
"sessions.detail.field.id": {
|
|
17
|
-
"sessions.detail.field.userId": {
|
|
18
|
-
"sessions.detail.field.createdAt": {
|
|
19
|
-
"sessions.detail.field.expiresAt": {
|
|
20
|
-
"sessions.detail.field.revokedAt": {
|
|
21
|
-
"sessions.detail.field.ip": {
|
|
22
|
-
"sessions.detail.field.userAgent": {
|
|
7
|
+
"screen:session-list.title": { en: "Sessions" },
|
|
8
|
+
"screen:session-detail.title": { en: "Session" },
|
|
9
|
+
"sessions:nav.sessionList": { en: "Sessions" },
|
|
10
|
+
"sessions.list.col.id": { en: "ID" },
|
|
11
|
+
"sessions.list.col.userId": { en: "User ID" },
|
|
12
|
+
"sessions.list.col.createdAt": { en: "Created" },
|
|
13
|
+
"sessions.list.col.expiresAt": { en: "Expires" },
|
|
14
|
+
"sessions.list.col.revokedAt": { en: "Revoked" },
|
|
15
|
+
"sessions.list.action.open": { en: "Details" },
|
|
16
|
+
"sessions.detail.field.id": { en: "ID" },
|
|
17
|
+
"sessions.detail.field.userId": { en: "User ID" },
|
|
18
|
+
"sessions.detail.field.createdAt": { en: "Created" },
|
|
19
|
+
"sessions.detail.field.expiresAt": { en: "Expires" },
|
|
20
|
+
"sessions.detail.field.revokedAt": { en: "Revoked" },
|
|
21
|
+
"sessions.detail.field.ip": { en: "IP address" },
|
|
22
|
+
"sessions.detail.field.userAgent": { en: "User agent" },
|
|
23
23
|
};
|
package/src/tags/i18n.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
type LocalizedString = { readonly
|
|
1
|
+
type LocalizedString = { readonly en: string };
|
|
2
2
|
|
|
3
3
|
export const TAGS_FEATURE_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
4
|
-
"screen:tag-list.title": {
|
|
4
|
+
"screen:tag-list.title": { en: "Tags" },
|
|
5
5
|
};
|
package/src/tags/web/i18n.ts
CHANGED
|
@@ -1,37 +1,11 @@
|
|
|
1
1
|
// @runtime client
|
|
2
2
|
// Default translation bundle for the tags UI. tagsClient() hangs it into the
|
|
3
3
|
// LocaleProvider as a fallback bundle — apps override individual keys via
|
|
4
|
-
// tagsClient({ translations
|
|
4
|
+
// tagsClient({ translations }). Keys follow `tags.<area>.<slug>`.
|
|
5
5
|
|
|
6
6
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
7
7
|
|
|
8
8
|
export const defaultTranslations: TranslationsByLocale = {
|
|
9
|
-
de: {
|
|
10
|
-
"tags.section.createMode": "Speichere zuerst den Eintrag, um Tags zu setzen.",
|
|
11
|
-
"tags.section.loading": "Lädt…",
|
|
12
|
-
"tags.section.empty": "Keine Tags gefunden.",
|
|
13
|
-
"tags.section.working": "Speichert…",
|
|
14
|
-
"tags.section.none": "Keine Tags",
|
|
15
|
-
"tags.section.edit": "Tags bearbeiten",
|
|
16
|
-
"tags.manage.newLabel": "Neuer Tag",
|
|
17
|
-
"tags.manage.namePlaceholder": "Tag-Name",
|
|
18
|
-
"tags.manage.scopeLabel": "Geltungsbereich (Entity-Typ, leer = global)",
|
|
19
|
-
"tags.manage.scopePlaceholder": "z. B. note (leer = überall)",
|
|
20
|
-
"tags.manage.create": "Tag anlegen",
|
|
21
|
-
"tags.manage.edit": "Bearbeiten",
|
|
22
|
-
"tags.manage.save": "Speichern",
|
|
23
|
-
"tags.manage.cancel": "Abbrechen",
|
|
24
|
-
"tags.manage.delete": "Löschen",
|
|
25
|
-
"tags.manage.toggle": "Tag umschalten",
|
|
26
|
-
"tags.manage.usage": "{count}×",
|
|
27
|
-
"tags.manage.deleteConfirmTitle": "Tag „{name}“ löschen?",
|
|
28
|
-
"tags.manage.deleteConfirmDesc":
|
|
29
|
-
"Entfernt ihn von {count} Objekten. Das lässt sich nicht rückgängig machen.",
|
|
30
|
-
"tags.picker.title": "Tags",
|
|
31
|
-
"tags.picker.done": "Fertig",
|
|
32
|
-
"tags.filter.label": "Nach Tag filtern",
|
|
33
|
-
"tags.filter.clear": "Filter zurücksetzen",
|
|
34
|
-
},
|
|
35
9
|
en: {
|
|
36
10
|
"tags.section.createMode": "Save the entity first to add tags.",
|
|
37
11
|
"tags.section.loading": "Loading…",
|
|
@@ -254,7 +254,7 @@ describe("textBlocksClient — content collections", () => {
|
|
|
254
254
|
});
|
|
255
255
|
|
|
256
256
|
describe("textBlocksClient — plain contentFormat editor wiring", () => {
|
|
257
|
-
const localeResolver = createStaticLocaleResolver({ locale: "
|
|
257
|
+
const localeResolver = createStaticLocaleResolver({ locale: "en" });
|
|
258
258
|
|
|
259
259
|
function Wrapper({ children }: { readonly children: ReactNode }): ReactNode {
|
|
260
260
|
return (
|
|
@@ -298,7 +298,7 @@ describe("textBlocksClient — plain contentFormat editor wiring", () => {
|
|
|
298
298
|
});
|
|
299
299
|
|
|
300
300
|
describe("textBlocksClient — findContentFormat resolves collectionId to the registered editor", () => {
|
|
301
|
-
const localeResolver = createStaticLocaleResolver({ locale: "
|
|
301
|
+
const localeResolver = createStaticLocaleResolver({ locale: "en" });
|
|
302
302
|
const RichStub: ContentEditorComponent = () => <div data-testid="rich-stub-editor" />;
|
|
303
303
|
|
|
304
304
|
function RichStubWrapper({ children }: { readonly children: ReactNode }): ReactNode {
|
|
@@ -52,7 +52,7 @@ function getEditor() {
|
|
|
52
52
|
return Editor;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
const localeResolver = createStaticLocaleResolver({ locale: "
|
|
55
|
+
const localeResolver = createStaticLocaleResolver({ locale: "en" });
|
|
56
56
|
|
|
57
57
|
function Wrapper({ children }: { readonly children: ReactNode }): ReactNode {
|
|
58
58
|
return (
|
|
@@ -80,7 +80,7 @@ describe("TextContentEditor — role-based write-access", () => {
|
|
|
80
80
|
const Editor = getEditor();
|
|
81
81
|
render(<Editor target={TARGET} onClose={() => {}} />, { wrapper: Wrapper });
|
|
82
82
|
|
|
83
|
-
const saveButton = screen.getByRole("button", { name: /
|
|
83
|
+
const saveButton = screen.getByRole("button", { name: /save/i });
|
|
84
84
|
expect(saveButton).toBeTruthy();
|
|
85
85
|
expect(saveButton.hasAttribute("disabled")).toBe(false);
|
|
86
86
|
|
|
@@ -93,7 +93,7 @@ describe("TextContentEditor — role-based write-access", () => {
|
|
|
93
93
|
const Editor = getEditor();
|
|
94
94
|
render(<Editor target={TARGET} onClose={() => {}} />, { wrapper: Wrapper });
|
|
95
95
|
|
|
96
|
-
expect(screen.getByRole("button", { name: /
|
|
96
|
+
expect(screen.getByRole("button", { name: /save/i })).toBeTruthy();
|
|
97
97
|
expect(screen.queryByText(/Read-only/)).toBeNull();
|
|
98
98
|
});
|
|
99
99
|
|
|
@@ -153,7 +153,7 @@ describe("TextContentEditor — handleSave", () => {
|
|
|
153
153
|
render(<Editor target={TARGET} onClose={() => {}} />, { wrapper: Wrapper });
|
|
154
154
|
|
|
155
155
|
await act(async () => {
|
|
156
|
-
fireEvent.click(screen.getByRole("button", { name: /
|
|
156
|
+
fireEvent.click(screen.getByRole("button", { name: /save/i }));
|
|
157
157
|
await Promise.resolve();
|
|
158
158
|
});
|
|
159
159
|
|
|
@@ -177,7 +177,7 @@ describe("TextContentEditor — handleSave", () => {
|
|
|
177
177
|
render(<Editor target={TARGET} onClose={() => {}} />, { wrapper: Wrapper });
|
|
178
178
|
|
|
179
179
|
await act(async () => {
|
|
180
|
-
fireEvent.click(screen.getByRole("button", { name: /
|
|
180
|
+
fireEvent.click(screen.getByRole("button", { name: /save/i }));
|
|
181
181
|
await Promise.resolve();
|
|
182
182
|
});
|
|
183
183
|
|
|
@@ -8,20 +8,6 @@
|
|
|
8
8
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
9
9
|
|
|
10
10
|
export const defaultTranslations: TranslationsByLocale = {
|
|
11
|
-
de: {
|
|
12
|
-
"template-resolver.editor.titleLabel": "Titel",
|
|
13
|
-
"template-resolver.editor.contentLabel": "Inhalt",
|
|
14
|
-
"template-resolver.editor.save": "Speichern",
|
|
15
|
-
"template-resolver.editor.saving": "Speichern…",
|
|
16
|
-
"template-resolver.editor.created": "Neu angelegt.",
|
|
17
|
-
"template-resolver.editor.saved": "Gespeichert.",
|
|
18
|
-
"template-resolver.editor.saveFailed": "Speichern fehlgeschlagen.",
|
|
19
|
-
"template-resolver.editor.networkError": "Netzwerkfehler beim Speichern.",
|
|
20
|
-
"template-resolver.editor.loading": "Lädt aktuellen Stand…",
|
|
21
|
-
"template-resolver.editor.loadFailed": "Konnte Block nicht laden",
|
|
22
|
-
"template-resolver.editor.readOnly":
|
|
23
|
-
"Read-only — TenantAdmin- oder SystemAdmin-Rolle für Änderungen erforderlich.",
|
|
24
|
-
},
|
|
25
11
|
en: {
|
|
26
12
|
"template-resolver.editor.titleLabel": "Title",
|
|
27
13
|
"template-resolver.editor.contentLabel": "Content",
|
|
@@ -5,7 +5,6 @@ import { AuthHandlers } from "../../auth-email-password/constants";
|
|
|
5
5
|
import { createConfigFeature } from "../../config/feature";
|
|
6
6
|
import { MEMBERS_SCREEN_ID, TenantHandlers, TenantQueries } from "../constants";
|
|
7
7
|
import { createTenantFeature } from "../feature";
|
|
8
|
-
import { defaultTranslations } from "../web/i18n";
|
|
9
8
|
|
|
10
9
|
describe("tenant members screen + handler access alignment", () => {
|
|
11
10
|
const features = [createConfigFeature(), createTenantFeature()];
|
|
@@ -38,7 +37,6 @@ describe("tenant members screen + handler access alignment", () => {
|
|
|
38
37
|
test("members nav label uses tenantClient i18n key (not feature:nav.* alias)", () => {
|
|
39
38
|
const nav = createTenantFeature().navs["members"];
|
|
40
39
|
expect(nav?.label).toBe("tenant.nav.members");
|
|
41
|
-
expect(defaultTranslations["de"]?.["tenant.nav.members"]).toBe("Team");
|
|
42
40
|
});
|
|
43
41
|
|
|
44
42
|
test("updateMemberRoles stays SystemAdmin/system-only (not on members screen)", () => {
|
package/src/tenant/i18n.ts
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
|
-
type LocalizedString = { readonly
|
|
1
|
+
type LocalizedString = { readonly en: string };
|
|
2
2
|
|
|
3
3
|
export const TENANT_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
4
|
-
"screen:tenant-list.title": {
|
|
5
|
-
"screen:tenant-edit.title": {
|
|
6
|
-
"screen:members.title": {
|
|
7
|
-
"tenant.nav.members": {
|
|
8
|
-
"tenant:entity:tenant:field:key": {
|
|
9
|
-
"tenant:entity:tenant:field:name": {
|
|
10
|
-
"tenant:entity:tenant:field:isEnabled": {
|
|
11
|
-
"tenant:entity:tenant:field:status": {
|
|
12
|
-
"tenant:entity:tenant:field:status:option:active": {
|
|
4
|
+
"screen:tenant-list.title": { en: "Tenants" },
|
|
5
|
+
"screen:tenant-edit.title": { en: "Edit tenant" },
|
|
6
|
+
"screen:members.title": { en: "Team" },
|
|
7
|
+
"tenant.nav.members": { en: "Team" },
|
|
8
|
+
"tenant:entity:tenant:field:key": { en: "Key" },
|
|
9
|
+
"tenant:entity:tenant:field:name": { en: "Name" },
|
|
10
|
+
"tenant:entity:tenant:field:isEnabled": { en: "Enabled" },
|
|
11
|
+
"tenant:entity:tenant:field:status": { en: "Status" },
|
|
12
|
+
"tenant:entity:tenant:field:status:option:active": { en: "Active" },
|
|
13
13
|
"tenant:entity:tenant:field:status:option:destroyRequested": {
|
|
14
|
-
de: "Löschung angefordert",
|
|
15
14
|
en: "Destroy requested",
|
|
16
15
|
},
|
|
17
16
|
"tenant:entity:tenant:field:status:option:destroying": {
|
|
18
|
-
de: "Wird gelöscht",
|
|
19
17
|
en: "Destroying",
|
|
20
18
|
},
|
|
21
19
|
"tenant:entity:tenant:field:status:option:destroyFailed": {
|
|
22
|
-
de: "Löschung fehlgeschlagen",
|
|
23
20
|
en: "Destroy failed",
|
|
24
21
|
},
|
|
25
|
-
"tenant:entity:tenant:field:status:option:destroyed": {
|
|
26
|
-
"tenant:entity:tenant:field:isEnabled:option:true": {
|
|
27
|
-
"tenant:entity:tenant:field:isEnabled:option:false": {
|
|
22
|
+
"tenant:entity:tenant:field:status:option:destroyed": { en: "Destroyed" },
|
|
23
|
+
"tenant:entity:tenant:field:isEnabled:option:true": { en: "Yes" },
|
|
24
|
+
"tenant:entity:tenant:field:isEnabled:option:false": { en: "No" },
|
|
28
25
|
};
|
package/src/tenant/web/i18n.ts
CHANGED
|
@@ -2,25 +2,6 @@
|
|
|
2
2
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
3
3
|
|
|
4
4
|
export const defaultTranslations: TranslationsByLocale = {
|
|
5
|
-
de: {
|
|
6
|
-
"tenant.members.title": "Mitglieder",
|
|
7
|
-
"tenant.members.loading": "Lade Mitglieder…",
|
|
8
|
-
"tenant.members.active": "Aktive Mitglieder",
|
|
9
|
-
"tenant.members.invite.title": "Neue Einladung",
|
|
10
|
-
"tenant.members.invite.email": "E-Mail",
|
|
11
|
-
"tenant.members.invite.role": "Rolle",
|
|
12
|
-
"tenant.members.invite.submit": "Einladung senden",
|
|
13
|
-
"tenant.members.invite.submitting": "Einladung wird gesendet…",
|
|
14
|
-
"tenant.members.invite.success": "Einladung an {email} gesendet",
|
|
15
|
-
"tenant.members.pending": "Ausstehende Einladungen",
|
|
16
|
-
"tenant.members.pending.empty": "Keine ausstehenden Einladungen.",
|
|
17
|
-
"tenant.members.cancel": "Zurückziehen",
|
|
18
|
-
"tenant.members.col.userId": "User-ID",
|
|
19
|
-
"tenant.members.col.roles": "Rollen",
|
|
20
|
-
"tenant.members.col.email": "E-Mail",
|
|
21
|
-
"tenant.members.col.expires": "Gültig bis",
|
|
22
|
-
"tenant.nav.members": "Team",
|
|
23
|
-
},
|
|
24
5
|
en: {
|
|
25
6
|
"tenant.members.title": "Members",
|
|
26
7
|
"tenant.members.loading": "Loading members…",
|
package/src/tier-engine/i18n.ts
CHANGED
|
@@ -1,33 +1,17 @@
|
|
|
1
1
|
// @runtime client
|
|
2
2
|
// Default-Bundles für den TierAdminScreen. Werden vom tierEngineClient()
|
|
3
3
|
// als Fallback-Bundle in den LocaleProvider gehängt — Apps überschreiben
|
|
4
|
-
// einzelne Keys via `tierEngineClient({ translations
|
|
4
|
+
// einzelne Keys via `tierEngineClient({ translations })`.
|
|
5
5
|
|
|
6
6
|
import type { TranslationsByLocale } from "@cosmicdrift/kumiko-renderer";
|
|
7
7
|
|
|
8
|
-
type LocalizedString = { readonly
|
|
8
|
+
type LocalizedString = { readonly en: string };
|
|
9
9
|
|
|
10
10
|
export const TIER_ENGINE_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
11
|
-
"screen:tier-admin.title": {
|
|
11
|
+
"screen:tier-admin.title": { en: "Assign tier manually" },
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
export const defaultTranslations: TranslationsByLocale = {
|
|
15
|
-
de: {
|
|
16
|
-
"screen:tier-admin.title": "Tier manuell zuweisen",
|
|
17
|
-
"tier-admin.title": "Tier manuell zuweisen",
|
|
18
|
-
"tier-admin.explainer":
|
|
19
|
-
"Weise einem Tenant ein Tier ohne Kauf zu. Der Grant wird als „manuell“ markiert und von einem späteren Billing-Sync nicht überschrieben.",
|
|
20
|
-
"tier-admin.tenant.label": "Tenant",
|
|
21
|
-
"tier-admin.current.label": "Aktuelles Tier",
|
|
22
|
-
"tier-admin.current.none": "— noch keins —",
|
|
23
|
-
"tier-admin.tier.label": "Neues Tier",
|
|
24
|
-
"tier-admin.submit": "Tier zuweisen",
|
|
25
|
-
"tier-admin.success": "Tier „{tier}“ zugewiesen.",
|
|
26
|
-
"tier-admin.error.generic": "Konnte das Tier nicht zuweisen.",
|
|
27
|
-
"tier-admin.error.load": "Tenants konnten nicht geladen werden.",
|
|
28
|
-
"tier-admin.error.noTiers":
|
|
29
|
-
"Diese App hat keine TierMap konfiguriert — es gibt keine zuweisbaren Tiers.",
|
|
30
|
-
},
|
|
31
15
|
en: {
|
|
32
16
|
"screen:tier-admin.title": "Assign tier manually",
|
|
33
17
|
"tier-admin.title": "Assign tier manually",
|
package/src/user/i18n.ts
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
type LocalizedString = { readonly
|
|
1
|
+
type LocalizedString = { readonly en: string };
|
|
2
2
|
|
|
3
3
|
export const USER_I18N: Readonly<Record<string, LocalizedString>> = {
|
|
4
|
-
"screen:user-list.title": {
|
|
5
|
-
"screen:user-edit.title": {
|
|
6
|
-
"user:entity:user:field:email": {
|
|
7
|
-
"user:entity:user:field:displayName": {
|
|
8
|
-
"user:entity:user:field:status": {
|
|
9
|
-
"user:entity:user:field:emailVerified": {
|
|
10
|
-
"user:entity:user:field:locale": {
|
|
11
|
-
"user:entity:user:field:timezone": {
|
|
12
|
-
"user:entity:user:field:status:option:active": {
|
|
13
|
-
"user:entity:user:field:status:option:restricted": {
|
|
4
|
+
"screen:user-list.title": { en: "Users" },
|
|
5
|
+
"screen:user-edit.title": { en: "Edit user" },
|
|
6
|
+
"user:entity:user:field:email": { en: "Email" },
|
|
7
|
+
"user:entity:user:field:displayName": { en: "Display name" },
|
|
8
|
+
"user:entity:user:field:status": { en: "Status" },
|
|
9
|
+
"user:entity:user:field:emailVerified": { en: "Email verified" },
|
|
10
|
+
"user:entity:user:field:locale": { en: "Locale" },
|
|
11
|
+
"user:entity:user:field:timezone": { en: "Timezone" },
|
|
12
|
+
"user:entity:user:field:status:option:active": { en: "Active" },
|
|
13
|
+
"user:entity:user:field:status:option:restricted": { en: "Restricted" },
|
|
14
14
|
"user:entity:user:field:status:option:deletionRequested": {
|
|
15
|
-
de: "Löschung angefordert",
|
|
16
15
|
en: "Deletion requested",
|
|
17
16
|
},
|
|
18
|
-
"user:entity:user:field:status:option:deleted": {
|
|
19
|
-
"user:entity:user:field:emailVerified:option:true": {
|
|
20
|
-
"user:entity:user:field:emailVerified:option:false": {
|
|
17
|
+
"user:entity:user:field:status:option:deleted": { en: "Deleted" },
|
|
18
|
+
"user:entity:user:field:emailVerified:option:true": { en: "Yes" },
|
|
19
|
+
"user:entity:user:field:emailVerified:option:false": { en: "No" },
|
|
21
20
|
};
|
|
@@ -10,6 +10,8 @@ import type {
|
|
|
10
10
|
EmailTransport,
|
|
11
11
|
} from "@cosmicdrift/kumiko-bundled-features/channel-email";
|
|
12
12
|
import type { TenantId } from "@cosmicdrift/kumiko-framework/engine";
|
|
13
|
+
import { registerMailTranslations } from "@cosmicdrift/kumiko-framework/i18n";
|
|
14
|
+
import { localeDeBundle } from "@cosmicdrift/kumiko-locale-de";
|
|
13
15
|
import {
|
|
14
16
|
makeDefaultDeletionExecutedEmail,
|
|
15
17
|
makeDefaultExportReadyEmail,
|
|
@@ -27,6 +29,8 @@ function capturingTransport(): { transport: EmailTransport; sent: EmailMessage[]
|
|
|
27
29
|
|
|
28
30
|
const TENANT_A = "00000000-0000-4000-8000-00000000000a" as TenantId;
|
|
29
31
|
|
|
32
|
+
registerMailTranslations("de", localeDeBundle);
|
|
33
|
+
|
|
30
34
|
describe("default-mailers dispatch", () => {
|
|
31
35
|
test("export-ready: rendert Template + sendet an userEmail ueber tenant-transport", async () => {
|
|
32
36
|
const cap = capturingTransport();
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { registerMailTranslations } from "@cosmicdrift/kumiko-framework/i18n";
|
|
3
|
+
import { localeDeBundle } from "@cosmicdrift/kumiko-locale-de";
|
|
2
4
|
import {
|
|
3
5
|
renderDeletionExecutedEmail,
|
|
4
6
|
renderDeletionRequestedEmail,
|
|
@@ -6,6 +8,8 @@ import {
|
|
|
6
8
|
renderExportReadyEmail,
|
|
7
9
|
} from "../email-templates";
|
|
8
10
|
|
|
11
|
+
registerMailTranslations("de", localeDeBundle);
|
|
12
|
+
|
|
9
13
|
describe("gdpr email-templates", () => {
|
|
10
14
|
test("export-ready: subject + download-button + formatted expiry, de/en differ", () => {
|
|
11
15
|
const en = renderExportReadyEmail({
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
22
22
|
import { resetTestTables, seedRow } from "@cosmicdrift/kumiko-framework/testing";
|
|
23
23
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
24
|
+
import { localeDe } from "@cosmicdrift/kumiko-locale-de";
|
|
24
25
|
import { createComplianceProfilesFeature } from "../../compliance-profiles";
|
|
25
26
|
import { configValuesTable, createConfigFeature, createConfigResolver } from "../../config";
|
|
26
27
|
import { createDataRetentionFeature, tenantRetentionOverrideEntity } from "../../data-retention";
|
|
@@ -63,6 +64,7 @@ beforeAll(async () => {
|
|
|
63
64
|
mailTransportInMemoryFeature,
|
|
64
65
|
// KEINE send*Email-Opts — die mail-foundation-Defaults muessen greifen.
|
|
65
66
|
createUserDataRightsFeature(),
|
|
67
|
+
localeDe(),
|
|
66
68
|
createUserDataRightsDefaultsFeature(),
|
|
67
69
|
],
|
|
68
70
|
});
|
|
@@ -14,6 +14,7 @@ import { authFoundationFeature } from "@cosmicdrift/kumiko-bundled-features/auth
|
|
|
14
14
|
import { asRawClient, selectMany } from "@cosmicdrift/kumiko-framework/bun-db";
|
|
15
15
|
import { type JobContext, SYSTEM_USER_ID } from "@cosmicdrift/kumiko-framework/engine";
|
|
16
16
|
import { createEventsTable } from "@cosmicdrift/kumiko-framework/event-store";
|
|
17
|
+
import { registerMailTranslations } from "@cosmicdrift/kumiko-framework/i18n";
|
|
17
18
|
import {
|
|
18
19
|
setupTestStack,
|
|
19
20
|
type TestStack,
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
} from "@cosmicdrift/kumiko-framework/stack";
|
|
23
24
|
import { seedRow } from "@cosmicdrift/kumiko-framework/testing";
|
|
24
25
|
import { getTemporal } from "@cosmicdrift/kumiko-framework/time";
|
|
26
|
+
import { localeDeBundle } from "@cosmicdrift/kumiko-locale-de";
|
|
25
27
|
import {
|
|
26
28
|
createComplianceProfilesFeature,
|
|
27
29
|
tenantComplianceProfileEntity,
|
|
@@ -134,6 +136,8 @@ async function seedPendingJob(): Promise<string> {
|
|
|
134
136
|
return res.jobId;
|
|
135
137
|
}
|
|
136
138
|
|
|
139
|
+
registerMailTranslations("de", localeDeBundle);
|
|
140
|
+
|
|
137
141
|
describe("run-export-jobs cron-context", () => {
|
|
138
142
|
test("Cron-Job-Kontext (configResolver, KEIN config) → Export läuft durch, bytesWritten > 0", async () => {
|
|
139
143
|
const jobId = await seedPendingJob();
|