import { pb, getPbImage } from "@/lib/pb"; import { notFound } from "next/navigation"; import Link from "next/link"; import { ArrowLeft, Calendar, Clock, ShieldCheck } from "lucide-react"; import { getDictionary } from "@/lib/dictionaries"; interface PBPost { id: string; collectionId: string; title: string; slug: string; content: string; image: string; lang: string; created: string; published: boolean; } interface Props { params: Promise<{ lang: string; slug: string }>; } export default async function BlogPostPage({ params }: Props) { const { lang, slug } = await params; const dict = await getDictionary(lang); let post: PBPost | undefined; // CMS-контент переведён только для части языков — коллекция `posts_` // для новых языков ещё не заведена в PocketBase. Пока для них нет перевода, // показываем английскую версию поста (тот же slug), а не 404. for (const fallbackLang of Array.from(new Set([lang, "en"]))) { try { // cache: "no-store" — в отличие от списка постов (там ISR на час), отдельный // пост всегда читается свежим: страница не самая горячая по трафику, а свежесть // контента (например, сразу после публикации) важнее экономии на кэше. post = await pb .collection(`posts_${fallbackLang}`) .getFirstListItem(`slug = "${slug}" && published = true`, { cache: "no-store", }); break; } catch (error) { // getFirstListItem бросает исключение, если запись не найдена (404 от PocketBase) // или не опубликована — пробуем следующий язык из фолбэка. } } if (!post) { notFound(); } return (
root@netrunner:~# {dict.blog.backBtn}
{post.image && (
{/* eslint-disable-next-line @next/next/no-img-element */} {post.title}
)}
{new Date(post.created).toLocaleDateString(lang || "en")} {dict.blog.readTime} {dict.blog.verified}

{post.title}

{dict.blog.endTransmission}
); }