import assert from "node:assert/strict"; import { user } from "../server/db/schema"; import { getSqliteConnection } from "../server/db/client"; import type { DomainActor } from "../server/domain/actor"; import { DomainService } from "../server/services/domain"; import { ContentTranslationService } from "../server/i18n/content"; import { ACTIVATION_CRITICAL_KEYS, I18nService, } from "../server/i18n/service"; const { db } = getSqliteConnection(); const owner: DomainActor = { authUserId: "phase5-owner", role: "freelancer", clientId: null, disabled: false, }; db.insert(user) .values({ id: owner.authUserId, name: "Phase 5 Owner", email: "phase5-owner@example.com", emailVerified: true, createdAt: new Date(), updatedAt: new Date(), }) .onConflictDoNothing() .run(); const i18n = new I18nService(db); i18n.listLocales(owner); if (!i18n.listLocales(owner).some((locale) => locale.code === "fr")) { i18n.createLocale(owner, { code: "fr", name: "French", nativeName: "Français", fallbackLocale: "en", }); } for (const fullKey of ACTIVATION_CRITICAL_KEYS) { const [namespace, ...keyParts] = fullKey.split("."); i18n.upsertUiTranslation(owner, { locale: "fr", namespace, key: keyParts.join("."), value: `fr:${fullKey}`, }); } i18n.updateLocale(owner, "fr", { status: "active" }); const domain = new DomainService(db, (() => { let next = 0; return () => `phase5-${++next}`; })()); const content = new ContentTranslationService(db); const project = domain.createProject(owner, { id: "phase5-project", type: "side_project", name: "Legacy fallback", translations: { tr: { name: "Çok dilli proje", description: "Türkçe açıklama", coverImageAlt: "Türkçe kapak", }, en: { name: "Multilingual project", description: "English description", coverImageAlt: "English cover", }, fr: { name: "Projet multilingue", description: "Description française", coverImageAlt: "Couverture française", }, }, }); assert.equal(project.name, "Çok dilli proje", "Default locale must be projected to legacy project.name."); assert.equal(project.description, "Türkçe açıklama"); const projectTranslations = content.listEntityTranslations("project", project.id); assert.equal(projectTranslations.filter((row) => row.field === "name").length, 3); assert.equal( content.resolveEntity("project", project, { locale: "fr", defaultLocale: "tr", translations: projectTranslations, }).name, "Projet multilingue", "Project must resolve according to selected locale.", ); const section = domain.addPlanningSection(owner, { id: "phase5-section", projectId: project.id, category: "overview", title: "Legacy section", translations: { tr: { title: "Planlama", content: "Türkçe içerik" }, en: { title: "Planning", content: "English content" }, fr: { title: "Planification", content: "Contenu français" }, }, }); assert.equal(section.title, "Planlama"); const task = domain.createTask(owner, { id: "phase5-task", projectId: project.id, title: "Legacy task", translations: { tr: { title: "Görev başlığı", description: "Türkçe görev" }, en: { title: "Task title", description: "English task" }, fr: { title: "Titre de tâche", description: "Tâche française" }, }, }); assert.equal(task.title, "Görev başlığı"); const batch = content.listBatch("task", [task.id]); assert.equal(batch.get(task.id)?.some((row) => row.locale === "fr" && row.value === "Titre de tâche"), true); domain.deleteTask(owner, task.id); assert.equal(content.listEntityTranslations("task", task.id).length, 0, "Task delete must remove content translations."); console.log("I18n phase 5 content translation smoke passed.");