feat(worker): verify-translations + set-test-locale (kvalitetsrapport & marknadstest)
- verify-translations.ts: läser DB och rapporterar täckning per språk, hur många som föll på verifieringen, titel=svenska-heuristik och stickprov (titel + steg 1). Kör efter svepet för att kvalitetskolla utan att ögna alla recept i appen. - set-test-locale.ts: sätter språk/region/valuta för ett testkonto utan psql, för att simulera olika marknader (t.ex. EUR så SEK-receptpriset döljs). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* Sätt locale-preferenser för ett testkonto (språk / region / valuta) – för att
|
||||
* simulera olika marknader utan psql. Skriver ut det sparade resultatet.
|
||||
*
|
||||
* pnpm --filter @app/worker exec tsx scripts/set-test-locale.ts <email> <languageTag> [regionCode] [currencyCode]
|
||||
*
|
||||
* Exempel:
|
||||
* # Full italiensk marknad (italienska + EUR + inga SEK-priser + IT-högtider):
|
||||
* ... set-test-locale.ts dev@hypbit.com it-IT IT EUR
|
||||
* # Bara dölja SEK-priset men behålla svenska marknaden/högtiderna:
|
||||
* ... set-test-locale.ts dev@hypbit.com it-IT SE EUR
|
||||
* # Tillbaka till svenskt:
|
||||
* ... set-test-locale.ts dev@hypbit.com sv-SE SE SEK
|
||||
*
|
||||
* region/valuta är valfria – utelämnas de rörs de inte (bara språket byts).
|
||||
* Byt sedan språk i appens profil (eller starta om appen) så cachen rensas.
|
||||
*
|
||||
* Körs i ett vanligt fönster (inte Fönster A/B/C). Kräver DATABASE_URL (.env).
|
||||
*/
|
||||
import { config as loadDotenv } from "dotenv";
|
||||
import { existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { eq } 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 [email, languageTag, regionCode, currencyCode] = process.argv.slice(2);
|
||||
if (!email || !languageTag) {
|
||||
console.error(
|
||||
"Användning: set-test-locale.ts <email> <languageTag> [regionCode] [currencyCode]",
|
||||
);
|
||||
console.error("Exempel: set-test-locale.ts dev@hypbit.com it-IT IT EUR");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { db, pool } = createDatabase(process.env.DATABASE_URL);
|
||||
const [user] = await db
|
||||
.select({ id: schema.users.id })
|
||||
.from(schema.users)
|
||||
.where(eq(schema.users.email, email))
|
||||
.limit(1);
|
||||
if (!user) throw new Error(`Hittar ingen användare med e-post "${email}".`);
|
||||
|
||||
const patch = {
|
||||
languageTag,
|
||||
...(regionCode ? { regionCode } : {}),
|
||||
...(currencyCode ? { currencyCode } : {}),
|
||||
};
|
||||
const [row] = await db
|
||||
.insert(schema.userLocalePreferences)
|
||||
.values({ userId: user.id, ...patch })
|
||||
.onConflictDoUpdate({
|
||||
target: schema.userLocalePreferences.userId,
|
||||
set: { ...patch, updatedAt: new Date() },
|
||||
})
|
||||
.returning();
|
||||
|
||||
console.log(`\n✓ Uppdaterade locale för ${email}:`);
|
||||
console.log(` language_tag = ${row?.languageTag}`);
|
||||
console.log(` region_code = ${row?.regionCode}`);
|
||||
console.log(` currency_code = ${row?.currencyCode} ${row?.currencyCode === "SEK" ? "(SEK-pris VISAS)" : "(receptpris DÖLJS tills riktpriser finns)"}`);
|
||||
console.log(`\nByt språk i appens profil (eller starta om appen) så cachen rensas och det slår igenom.`);
|
||||
|
||||
await pool.end();
|
||||
}
|
||||
main().then(
|
||||
() => process.exit(0),
|
||||
(e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user