feat(blog): جداسازی دوزبانهٔ اسلاگ/کلیدواژه/نویسنده/تگ‌ها/متا + میگریشن ۰۰۰۲، رفع «دقیقه مطالعه دقیقه»، فونت مقاله ۱۵/۱۷px، جدول تیپ‌تپ در ادیتور، مسیر /en/blog با slug_en

This commit is contained in:
aramesh-site deploy
2026-10-06 10:11:55 +00:00
parent 426dc783df
commit 61a2e95278
11 changed files with 862 additions and 197 deletions
+6 -17
View File
@@ -2,9 +2,10 @@
// فرانت‌اند هر دو زبان را در یک درخواست از GET /api/site می‌گیرد و سوییچ زبان
// بی‌درنگ و بدون درخواست تازه انجام می‌شود. داده خام برای پنل مدیریت دست‌نخورده می‌ماند.
import type { Article, ArticleBodyDoc } from '../data/site'
import type { Article } from '../data/site'
import type { SiteData } from '../api'
import type { Lang } from './lang'
import { docHasText } from '../utils/tiptapDoc'
/** متن انگلیسی فقط وقتی جایگزین می‌شود که واقعاً چیزی نوشته شده باشد */
const s = (fa: string, en?: string | null): string => (en && en.trim() ? en : fa)
@@ -12,22 +13,6 @@ const s = (fa: string, en?: string | null): string => (en && en.trim() ? en : fa
/** لیست انگلیسی فقط وقتی جایگزین می‌شود که غیرخالی باشد */
const list = <T,>(fa: T[], en?: T[] | null): T[] => (en && en.length ? en : fa)
/** سند TipTap انگلیسی فقط وقتی متن واقعی دارد جایگزین بدنه فارسی می‌شود */
function docHasText(doc: unknown): boolean {
if (!doc || typeof doc !== 'object') return false
const content = (doc as ArticleBodyDoc).content
if (!Array.isArray(content)) return false
let found = false
const walk = (node: unknown): void => {
if (!node || typeof node !== 'object' || found) return
const n = node as { type?: string; text?: string; content?: unknown[] }
if (n.type === 'text' && typeof n.text === 'string' && n.text.trim()) found = true
n.content?.forEach(walk)
}
content.forEach(walk)
return found
}
export function localizeSite(data: SiteData, lang: Lang): SiteData {
if (lang === 'fa') return data
return {
@@ -93,13 +78,17 @@ export function localizeSite(data: SiteData, lang: Lang): SiteData {
})),
articles: data.articles.map((a: Article) => ({
...a,
slug: s(a.slug, a.slug_en),
title: s(a.title, a.title_en),
date: s(a.date, a.date_en),
category: s(a.category, a.category_en),
read: s(a.read, a.read_en),
author: s(a.author ?? '', a.author_en),
excerpt: s(a.excerpt, a.excerpt_en),
meta_description: s(a.meta_description ?? '', a.meta_description_en),
body: docHasText(a.body_en) ? a.body_en! : a.body,
faqs: list(a.faqs ?? [], a.faqs_en),
tags: list(a.tags ?? [], a.tags_en),
})),
testimonials: data.testimonials.map((tm) => ({
...tm,