0ecd78f7e3
- Litet diagnostikscript: skriver ut recipe_translations per språk × status (draft_ai vs published), antal publicerade recept, och varje kontos language_tag. Så man slipper psql för att se hur långt svepet kommit och vilket innehållsspråk ett testkonto faktiskt har. Co-Authored-By: Claude <noreply@anthropic.com>
84 lines
2.9 KiB
TypeScript
84 lines
2.9 KiB
TypeScript
/**
|
||
* Snabb statusöversikt för receptöversättningarna – så du slipper psql.
|
||
*
|
||
* pnpm --filter @app/worker exec tsx scripts/translation-status.ts
|
||
*
|
||
* Visar tre saker:
|
||
* 1. recipe_translations per språk × status (draft_ai = workern klar men ej
|
||
* publicerad; published = syns i appen).
|
||
* 2. Antal publicerade recept (referens för hur många × språk ett fullt svep är).
|
||
* 3. Varje kontos innehållsspråk (language_tag) – det styr vilket språk
|
||
* recepttexten hämtas på, oberoende av UI-språket.
|
||
*
|
||
* Körs i ett vanligt fönster (inte Fönster A/B/C) – engångskommando som avslutas.
|
||
* Kräver DATABASE_URL (laddas från .env precis som translate-recipes.ts).
|
||
*/
|
||
import { config as loadDotenv } from "dotenv";
|
||
import { existsSync } from "node:fs";
|
||
import path from "node:path";
|
||
import { eq, sql } from "drizzle-orm";
|
||
import { createDatabase, schema } from "@app/database";
|
||
|
||
for (const candidate of [".env", "../.env", "../../.env"]) {
|
||
const p = path.resolve(process.cwd(), candidate);
|
||
if (existsSync(p)) {
|
||
loadDotenv({ path: p });
|
||
break;
|
||
}
|
||
}
|
||
|
||
async function main() {
|
||
if (!process.env.DATABASE_URL) throw new Error("Sätt DATABASE_URL.");
|
||
const { db, pool } = createDatabase(process.env.DATABASE_URL);
|
||
|
||
const rows = await db
|
||
.select({
|
||
lang: schema.recipeTranslations.languageTag,
|
||
status: schema.recipeTranslations.status,
|
||
n: sql<number>`count(*)::int`,
|
||
})
|
||
.from(schema.recipeTranslations)
|
||
.groupBy(schema.recipeTranslations.languageTag, schema.recipeTranslations.status)
|
||
.orderBy(schema.recipeTranslations.languageTag, schema.recipeTranslations.status);
|
||
|
||
console.log("\n=== recipe_translations (språk × status) ===");
|
||
if (rows.length === 0) {
|
||
console.log(" (inga rader alls – workern har inte skapat några översättningar än)");
|
||
} else {
|
||
for (const r of rows) console.log(` ${r.lang.padEnd(7)}${r.status.padEnd(12)}${r.n}`);
|
||
}
|
||
|
||
const [rec] = await db
|
||
.select({ n: sql<number>`count(*)::int` })
|
||
.from(schema.recipes)
|
||
.where(eq(schema.recipes.status, "published"));
|
||
console.log(`\nPublicerade recept totalt: ${rec?.n ?? 0}`);
|
||
|
||
const accounts = await db
|
||
.select({
|
||
email: schema.users.email,
|
||
lang: schema.userLocalePreferences.languageTag,
|
||
region: schema.userLocalePreferences.regionCode,
|
||
})
|
||
.from(schema.userLocalePreferences)
|
||
.innerJoin(schema.users, eq(schema.users.id, schema.userLocalePreferences.userId))
|
||
.orderBy(schema.users.email);
|
||
console.log("\n=== konto → innehållsspråk (language_tag) ===");
|
||
if (accounts.length === 0) {
|
||
console.log(" (inga konton har satt språk – alla faller på sv-SE)");
|
||
} else {
|
||
for (const a of accounts) {
|
||
console.log(` ${(a.email ?? "?").padEnd(30)}${(a.lang ?? "?").padEnd(8)}region=${a.region}`);
|
||
}
|
||
}
|
||
|
||
await pool.end();
|
||
}
|
||
main().then(
|
||
() => process.exit(0),
|
||
(e) => {
|
||
console.error(e);
|
||
process.exit(1);
|
||
},
|
||
);
|