feat(worker): --limit=N i translate-recipes för billig pilot över alla språk
- translate-recipes.ts får en valfri --limit=N som bara köar de N första (alfabetiskt) publicerade recepten × målspråk. Syfte: kvalitetskolla en handfull recept på ALLA språk innan hela svepet (~496 × 11) körs och betalas. - Skriver ut vilka recept som valts i pilot-läge så man vet vad man ska granska. - Oförändrat i övrigt: idempotent, resumbar, draft_ai -> verifiering -> publish-translations.ts publicerar bara det som klarat verifieringen. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
* pnpm --filter @app/worker exec tsx scripts/translate-recipes.ts es # bara spanska (testa först!)
|
||||
* pnpm --filter @app/worker exec tsx scripts/translate-recipes.ts es,de # flera
|
||||
* pnpm --filter @app/worker exec tsx scripts/translate-recipes.ts all # alla 11 språk
|
||||
* pnpm --filter @app/worker exec tsx scripts/translate-recipes.ts all --limit=5 # PILOT: 5 recept × alla språk
|
||||
*
|
||||
* Kräver DATABASE_URL och REDIS_URL i miljön (samma som API/worker använder).
|
||||
*/
|
||||
@@ -37,9 +38,17 @@ const LANGS = ["en", "da", "de", "es", "fi", "fr", "it", "nb", "nl", "pl", "pt"]
|
||||
|
||||
async function main() {
|
||||
if (!process.env.DATABASE_URL) throw new Error("Sätt DATABASE_URL.");
|
||||
const arg = (process.argv[2] ?? "all").toLowerCase();
|
||||
const positional = process.argv.slice(2).filter((a) => !a.startsWith("--"));
|
||||
const arg = (positional[0] ?? "all").toLowerCase();
|
||||
const targets =
|
||||
arg === "all" ? LANGS : arg.split(",").map((s) => s.trim()).filter(Boolean);
|
||||
// Valfri pilotgräns: --limit=N översätter bara de N första publicerade recepten
|
||||
// (alfabetiskt) × målspråk – billig kvalitetskoll innan hela svepet.
|
||||
const limitFlag = process.argv.find((a) => a.startsWith("--limit="));
|
||||
const limit = limitFlag ? Number(limitFlag.split("=")[1]) : null;
|
||||
if (limitFlag && (!Number.isInteger(limit) || (limit ?? 0) <= 0)) {
|
||||
throw new Error("--limit=N kräver ett positivt heltal, t.ex. --limit=5");
|
||||
}
|
||||
for (const l of targets) {
|
||||
if (!LANGS.includes(l)) throw new Error(`Okänt språk: ${l}. Giltiga: ${LANGS.join(", ")}, all`);
|
||||
}
|
||||
@@ -50,10 +59,18 @@ async function main() {
|
||||
});
|
||||
const queue = new Queue(JOB_QUEUE_NAME, { connection });
|
||||
|
||||
const recipes = await db
|
||||
.select({ id: schema.recipes.id })
|
||||
const baseQuery = db
|
||||
.select({ id: schema.recipes.id, title: schema.recipes.titleSv })
|
||||
.from(schema.recipes)
|
||||
.where(eq(schema.recipes.status, "published"));
|
||||
.where(eq(schema.recipes.status, "published"))
|
||||
.orderBy(schema.recipes.titleSv);
|
||||
const recipes = limit ? await baseQuery.limit(limit) : await baseQuery;
|
||||
if (limit) {
|
||||
console.log(
|
||||
`PILOT-läge: ${recipes.length} recept (alfabetiskt först) × ${targets.length} språk:`,
|
||||
);
|
||||
for (const r of recipes) console.log(` • ${r.title}`);
|
||||
}
|
||||
const existing = await db
|
||||
.select({ r: schema.recipeTranslations.recipeId, l: schema.recipeTranslations.languageTag })
|
||||
.from(schema.recipeTranslations);
|
||||
|
||||
Reference in New Issue
Block a user