- Install next-intl@4 with cookie-based locale switching (NEXT_LOCALE) - Add LanguageSwitcher component in Sidebar footer - Translate Nav, PostTypeSheet, Feed, Explore, WelcomeCard, PetForm, AvatarUpload, and Onboarding pages (EN + DE) - Add SpeciesTranslation and BreedTranslation DB models for locale-aware taxonomy; listSpecies and listBreeds accept optional locale param - Seed German translations for all 3 species and 45 breeds - Add SQL migration script for Supabase (add_i18n_translations.sql) - fix(invite): secure cookie flag and set-invite route for HTTPS
204 lines
5.2 KiB
TypeScript
204 lines
5.2 KiB
TypeScript
import { PrismaClient } from "@prisma/client";
|
|
import { PrismaPg } from "@prisma/adapter-pg";
|
|
import { Pool } from "pg";
|
|
|
|
/**
|
|
* Seed script for the PawFeed database.
|
|
* Seeds Species (Dog, Cat, Bird) and Breed taxonomy idempotently.
|
|
* Uses upsert so it is safe to run multiple times.
|
|
*
|
|
* Run: npx tsx prisma/seed.ts
|
|
* Or: npx prisma db seed
|
|
*/
|
|
|
|
const databaseUrl = process.env.DATABASE_URL;
|
|
if (!databaseUrl) {
|
|
throw new Error(
|
|
"DATABASE_URL is not set. Please add it to .env.local first."
|
|
);
|
|
}
|
|
|
|
const adapter = new PrismaPg(new Pool({ connectionString: databaseUrl }));
|
|
const prisma = new PrismaClient({ adapter });
|
|
|
|
const DOG_BREEDS = [
|
|
"Labrador Retriever",
|
|
"Golden Retriever",
|
|
"German Shepherd",
|
|
"French Bulldog",
|
|
"Bulldog",
|
|
"Poodle",
|
|
"Beagle",
|
|
"Rottweiler",
|
|
"German Shorthaired Pointer",
|
|
"Dachshund",
|
|
"Pembroke Welsh Corgi",
|
|
"Australian Shepherd",
|
|
"Yorkshire Terrier",
|
|
"Boxer",
|
|
"Cavalier King Charles Spaniel",
|
|
"Doberman Pinscher",
|
|
"Great Dane",
|
|
"Miniature Schnauzer",
|
|
"Siberian Husky",
|
|
"Border Collie",
|
|
];
|
|
|
|
const CAT_BREEDS = [
|
|
"Domestic Shorthair",
|
|
"Domestic Longhair",
|
|
"Maine Coon",
|
|
"Ragdoll",
|
|
"Siamese",
|
|
"Persian",
|
|
"Bengal",
|
|
"British Shorthair",
|
|
"Sphynx",
|
|
"Scottish Fold",
|
|
"American Shorthair",
|
|
"Abyssinian",
|
|
"Norwegian Forest Cat",
|
|
"Birman",
|
|
"Russian Blue",
|
|
];
|
|
|
|
const BIRD_BREEDS = [
|
|
"Budgerigar (Budgie)",
|
|
"Cockatiel",
|
|
"Lovebird",
|
|
"African Grey Parrot",
|
|
"Cockatoo",
|
|
"Conure",
|
|
"Macaw",
|
|
"Canary",
|
|
"Finch",
|
|
"Amazon Parrot",
|
|
];
|
|
|
|
const SPECIES_DE: Record<string, string> = {
|
|
"Dog": "Hund",
|
|
"Cat": "Katze",
|
|
"Bird": "Vogel",
|
|
};
|
|
|
|
const DOG_BREEDS_DE: Record<string, string> = {
|
|
"Labrador Retriever": "Labrador Retriever",
|
|
"Golden Retriever": "Golden Retriever",
|
|
"German Shepherd": "Deutscher Schäferhund",
|
|
"French Bulldog": "Französische Bulldogge",
|
|
"Bulldog": "Bulldogge",
|
|
"Poodle": "Pudel",
|
|
"Beagle": "Beagle",
|
|
"Rottweiler": "Rottweiler",
|
|
"German Shorthaired Pointer": "Deutsch Kurzhaar",
|
|
"Dachshund": "Dackel",
|
|
"Pembroke Welsh Corgi": "Pembroke Welsh Corgi",
|
|
"Australian Shepherd": "Australian Shepherd",
|
|
"Yorkshire Terrier": "Yorkshire Terrier",
|
|
"Boxer": "Boxer",
|
|
"Cavalier King Charles Spaniel": "Cavalier King Charles Spaniel",
|
|
"Doberman Pinscher": "Dobermann",
|
|
"Great Dane": "Deutsche Dogge",
|
|
"Miniature Schnauzer": "Zwergschnauzer",
|
|
"Siberian Husky": "Sibirischer Husky",
|
|
"Border Collie": "Border Collie",
|
|
};
|
|
|
|
const CAT_BREEDS_DE: Record<string, string> = {
|
|
"Domestic Shorthair": "Europäisch Kurzhaar",
|
|
"Domestic Longhair": "Europäisch Langhaar",
|
|
"Maine Coon": "Maine Coon",
|
|
"Ragdoll": "Ragdoll",
|
|
"Siamese": "Siamkatze",
|
|
"Persian": "Perserkatze",
|
|
"Bengal": "Bengalkatze",
|
|
"British Shorthair": "Britisch Kurzhaar",
|
|
"Sphynx": "Sphynx",
|
|
"Scottish Fold": "Scottish Fold",
|
|
"American Shorthair": "Amerikanisch Kurzhaar",
|
|
"Abyssinian": "Abessinier",
|
|
"Norwegian Forest Cat": "Norwegische Waldkatze",
|
|
"Birman": "Heilige Birma",
|
|
"Russian Blue": "Russisch Blau",
|
|
};
|
|
|
|
const BIRD_BREEDS_DE: Record<string, string> = {
|
|
"Budgerigar (Budgie)": "Wellensittich",
|
|
"Cockatiel": "Nymphensittich",
|
|
"Lovebird": "Unzertrennliche",
|
|
"African Grey Parrot": "Graupapagei",
|
|
"Cockatoo": "Kakadu",
|
|
"Conure": "Sittich",
|
|
"Macaw": "Ara",
|
|
"Canary": "Kanarienvogel",
|
|
"Finch": "Fink",
|
|
"Amazon Parrot": "Amazone",
|
|
};
|
|
|
|
const BREED_DE_BY_SPECIES: Record<string, Record<string, string>> = {
|
|
"Dog": DOG_BREEDS_DE,
|
|
"Cat": CAT_BREEDS_DE,
|
|
"Bird": BIRD_BREEDS_DE,
|
|
};
|
|
|
|
async function main() {
|
|
console.log("Seeding species...");
|
|
|
|
const speciesData = [
|
|
{ name: "Dog", breeds: DOG_BREEDS },
|
|
{ name: "Cat", breeds: CAT_BREEDS },
|
|
{ name: "Bird", breeds: BIRD_BREEDS },
|
|
];
|
|
|
|
for (const s of speciesData) {
|
|
const species = await prisma.species.upsert({
|
|
where: { name: s.name },
|
|
update: {},
|
|
create: { name: s.name },
|
|
});
|
|
console.log(` Upserted species: ${species.name} (${species.id})`);
|
|
|
|
const deSpeciesName = SPECIES_DE[s.name];
|
|
if (deSpeciesName) {
|
|
await prisma.speciesTranslation.upsert({
|
|
where: { speciesId_locale: { speciesId: species.id, locale: "de" } },
|
|
update: { name: deSpeciesName },
|
|
create: { speciesId: species.id, locale: "de", name: deSpeciesName },
|
|
});
|
|
}
|
|
|
|
console.log(` Seeding ${s.breeds.length} breeds for ${species.name}...`);
|
|
const breedDeMap = BREED_DE_BY_SPECIES[s.name] ?? {};
|
|
|
|
for (const breedName of s.breeds) {
|
|
const breed = await prisma.breed.upsert({
|
|
where: { speciesId_name: { speciesId: species.id, name: breedName } },
|
|
update: {},
|
|
create: { speciesId: species.id, name: breedName },
|
|
});
|
|
|
|
const deBreedName = breedDeMap[breedName];
|
|
if (deBreedName) {
|
|
await prisma.breedTranslation.upsert({
|
|
where: { breedId_locale: { breedId: breed.id, locale: "de" } },
|
|
update: { name: deBreedName },
|
|
create: { breedId: breed.id, locale: "de", name: deBreedName },
|
|
});
|
|
}
|
|
|
|
console.log(` Upserted breed: ${breed.name}`);
|
|
}
|
|
}
|
|
|
|
console.log("Seeding complete.");
|
|
}
|
|
|
|
main()
|
|
.catch((e) => {
|
|
console.error(e);
|
|
process.exit(1);
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect();
|
|
});
|