Files
neta/scripts/i18n-phase5-smoke.ts

129 lines
3.7 KiB
TypeScript

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.");