diff --git a/prisma/schema.prisma b/prisma/schema.prisma index c075c9f7..d74c4fec 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -102,12 +102,24 @@ model BookOtherNames { model Genre { id String @id slug String @unique - name String + + nameTranslations GenreName[] + transliteration String? numberOfBooks Int @default(0) books Book[] } +model GenreName { + locale String + text String + + genreId String + genre Genre @relation(fields: [genreId], references: [id], onDelete: Cascade, onUpdate: Cascade) + + @@id([genreId, locale]) +} + enum LocationType { Died Born diff --git a/src/app/[locale]/(entityPages)/genre/[genreSlug]/opengraph-image.tsx b/src/app/[locale]/(entityPages)/genre/[genreSlug]/opengraph-image.tsx index 5d6c197a..9a47421d 100644 --- a/src/app/[locale]/(entityPages)/genre/[genreSlug]/opengraph-image.tsx +++ b/src/app/[locale]/(entityPages)/genre/[genreSlug]/opengraph-image.tsx @@ -3,6 +3,7 @@ import { loadFileOnEdge } from "@/lib/edge"; import { notFound } from "next/navigation"; import { ImageResponse } from "next/og"; import { findGenreBySlug } from "@/server/services/genres"; +import { getPrimaryLocalizedText } from "@/server/db/localization"; export const runtime = "edge"; @@ -30,10 +31,12 @@ export async function generateImageMetadata({ const genre = await findGenreBySlug(genreSlug); if (!genre) return []; + const primaryText = getPrimaryLocalizedText(genre.nameTranslations, "en"); + return [ { id: "main", - alt: genre.name, + alt: primaryText, contentType: "image/png", size, }, @@ -51,6 +54,8 @@ export default async function Image({ notFound(); } + const primaryText = getPrimaryLocalizedText(genre.nameTranslations, "en"); + // Font const [calSans, family] = await Promise.all([ loadFileOnEdge.asArrayBuffer(fonts.calSans), @@ -71,7 +76,7 @@ export default async function Image({ fontFamily: "Cal Sans", }} > - {genre.name} + {primaryText} {/*
import("@/components/year-filter"), {
ssr: false,
@@ -28,10 +30,13 @@ export const generateMetadata = async ({
const genre = await findGenreBySlug(genreSlug);
if (!genre) return;
+ const locale = await getPathLocale();
+ const primaryText = getPrimaryLocalizedText(genre.nameTranslations, locale);
+
return getMetadata({
hasImage: true,
pagePath: navigation.genres.bySlug(genreSlug),
- title: genre.name,
+ title: primaryText,
});
};
@@ -41,6 +46,7 @@ async function GenrePage({
routeParams: { genreSlug },
searchParams,
}: GenrePageProps) {
+ const locale = await getPathLocale();
const genre = await findGenreBySlug(decodeURIComponent(genreSlug));
if (!genre) {
@@ -63,7 +69,7 @@ async function GenrePage({
},
});
- const primaryName = genre.name;
+ const primaryName = getPrimaryLocalizedText(genre.nameTranslations, locale);
const secondaryName = null;
return (
diff --git a/src/app/[locale]/t/[bookId]/_components/content-tab/index.tsx b/src/app/[locale]/t/[bookId]/_components/content-tab/index.tsx
index 7a15f232..d074a2cd 100644
--- a/src/app/[locale]/t/[bookId]/_components/content-tab/index.tsx
+++ b/src/app/[locale]/t/[bookId]/_components/content-tab/index.tsx
@@ -321,7 +321,10 @@ export default function ContentTab({ bookResponse }: TabProps) {
variant="secondary"
className="font-normal"
>
- {genre.name}
+ {getPrimaryLocalizedText(
+ genre.nameTranslations,
+ pathLocale,
+ )}
))}
diff --git a/src/components/genres-filter/client.tsx b/src/components/genres-filter/client.tsx
index 37efa44a..03009bb6 100644
--- a/src/components/genres-filter/client.tsx
+++ b/src/components/genres-filter/client.tsx
@@ -8,6 +8,8 @@ import FilterContainer from "@/components/search-results/filter-container";
import { useSearchParams, type ReadonlyURLSearchParams } from "next/navigation";
import { useFormatter, useTranslations } from "next-intl";
import type { findAllGenresWithBooksCount } from "@/server/services/genres";
+import { getPrimaryLocalizedText } from "@/server/db/localization";
+import { usePathLocale } from "@/lib/locale/utils";
const DEBOUNCE_DELAY = 300;
@@ -50,6 +52,7 @@ export default function _GenresFilter({
const { replace } = useRouter();
const searchParams = useSearchParams();
const [size, setSize] = useState(10);
+ const locale = usePathLocale();
const genreIdToGenreName = useMemo(() => {
return Object.fromEntries(genres.map((item) => [item.id, item]));
@@ -152,7 +155,11 @@ export default function _GenresFilter({
// const count = genreIdToBooksCount[genre.genreId.toLowerCase()] ?? 0;
const booksCount = formatter.number(genre._count.books);
- const title = `${genre.name} (${booksCount})`;
+ const primaryText = getPrimaryLocalizedText(
+ genre.nameTranslations,
+ locale,
+ );
+ const title = `${primaryText} (${booksCount})`;
return (