feat(worker): translation-status.ts – snabb översikt över översättningsläget
- 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>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* 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);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user