// بومی‌سازی درخت داده سایت — انتخاب فیلدهای انگلیسی با برگشت به فارسی. // فرانت‌اند هر دو زبان را در یک درخواست از GET /api/site می‌گیرد و سوییچ زبان // بی‌درنگ و بدون درخواست تازه انجام می‌شود. داده خام برای پنل مدیریت دست‌نخورده می‌ماند. import type { Article, ArticleBodyDoc } from '../data/site' import type { SiteData } from '../api' import type { Lang } from './lang' /** متن انگلیسی فقط وقتی جایگزین می‌شود که واقعاً چیزی نوشته شده باشد */ const s = (fa: string, en?: string | null): string => (en && en.trim() ? en : fa) /** لیست انگلیسی فقط وقتی جایگزین می‌شود که غیرخالی باشد */ const list = (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 { brand: { ...data.brand, name: s(data.brand.name, data.brand.name_en), address: s(data.brand.address, data.brand.address_en), }, nav: data.nav.map((n) => ({ ...n, label: s(n.label, n.label_en) })), hero: { ...data.hero, kicker: s(data.hero.kicker, data.hero.kicker_en), title: s(data.hero.title, data.hero.title_en), title_highlight: s(data.hero.title_highlight, data.hero.title_highlight_en), subtitle: s(data.hero.subtitle, data.hero.subtitle_en), badge_value: s(data.hero.badge_value, data.hero.badge_value_en), badge_label: s(data.hero.badge_label, data.hero.badge_label_en), cta_primary_label: s(data.hero.cta_primary_label, data.hero.cta_primary_label_en), cta_secondary_label: s(data.hero.cta_secondary_label, data.hero.cta_secondary_label_en), scroll_label: s(data.hero.scroll_label, data.hero.scroll_label_en), }, story: { ...data.story, title: s(data.story.title, data.story.title_en), paragraphs: list(data.story.paragraphs, data.story.paragraphs_en), quote: s(data.story.quote, data.story.quote_en), quote_author: s(data.story.quote_author, data.story.quote_author_en), stat1_value: s(data.story.stat1_value, data.story.stat1_value_en), stat1_label: s(data.story.stat1_label, data.story.stat1_label_en), stat2_value: s(data.story.stat2_value, data.story.stat2_value_en), stat2_label: s(data.story.stat2_label, data.story.stat2_label_en), link_label: s(data.story.link_label, data.story.link_label_en), bento: list(data.story.bento, data.story.bento_en), }, section_headings: data.section_headings.map((h) => ({ ...h, label: s(h.label, h.label_en), title: s(h.title, h.title_en), lead: s(h.lead, h.lead_en), cta_label: s(h.cta_label, h.cta_label_en), })), page_heroes: data.page_heroes.map((p) => ({ ...p, title: s(p.title, p.title_en), lead: s(p.lead, p.lead_en), })), services: data.services.map((sv) => ({ ...sv, title: s(sv.title, sv.title_en), desc: s(sv.desc, sv.desc_en), })), projects: data.projects.map((p) => ({ ...p, title: s(p.title, p.title_en), location: s(p.location, p.location_en), year: s(p.year, p.year_en), area: s(p.area, p.area_en), floors: s(p.floors, p.floors_en), units: s(p.units, p.units_en), client: s(p.client, p.client_en), summary: s(p.summary, p.summary_en), body: list(p.body, p.body_en), })), articles: data.articles.map((a: Article) => ({ ...a, 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), excerpt: s(a.excerpt, a.excerpt_en), body: docHasText(a.body_en) ? a.body_en! : a.body, })), testimonials: data.testimonials.map((tm) => ({ ...tm, name: s(tm.name, tm.name_en), role: s(tm.role, tm.role_en), quote: s(tm.quote, tm.quote_en), })), faqs: data.faqs.map((f) => ({ ...f, question: s(f.question, f.question_en), answer: s(f.answer, f.answer_en), })), team: data.team.map((m) => ({ ...m, name: s(m.name, m.name_en), role: s(m.role, m.role_en), bio: s(m.bio, m.bio_en), })), timeline: data.timeline.map((tm) => ({ ...tm, year: s(tm.year, tm.year_en), title: s(tm.title, tm.title_en), desc: s(tm.desc, tm.desc_en), })), stats: data.stats.map((st) => ({ ...st, suffix: s(st.suffix, st.suffix_en), label: s(st.label, st.label_en), })), why_us: data.why_us.map((w) => ({ ...w, title: s(w.title, w.title_en), desc: s(w.desc, w.desc_en), })), before_after: { ...data.before_after, title: s(data.before_after.title, data.before_after.title_en), lead: s(data.before_after.lead, data.before_after.lead_en), before_label: s(data.before_after.before_label, data.before_after.before_label_en), after_label: s(data.before_after.after_label, data.before_after.after_label_en), }, investment_models: data.investment_models.map((im) => ({ ...im, title: s(im.title, im.title_en), desc: s(im.desc, im.desc_en), points: list(im.points, im.points_en), })), process_steps: data.process_steps.map((ps) => ({ ...ps, step: s(ps.step, ps.step_en), title: s(ps.title, ps.title_en), desc: s(ps.desc, ps.desc_en), })), offices: data.offices.map((o) => ({ ...o, city: s(o.city, o.city_en), address: s(o.address, o.address_en), hours: s(o.hours, o.hours_en), })), gallery: data.gallery.map((g) => ({ ...g, alt: s(g.alt, g.alt_en) })), status_labels: data.status_labels.map((sl) => ({ ...sl, label: s(sl.label, sl.label_en) })), contact_section: { ...data.contact_section, label: s(data.contact_section.label, data.contact_section.label_en), title: s(data.contact_section.title, data.contact_section.title_en), lead: s(data.contact_section.lead, data.contact_section.lead_en), address_label: s(data.contact_section.address_label, data.contact_section.address_label_en), phone_label: s(data.contact_section.phone_label, data.contact_section.phone_label_en), email_label: s(data.contact_section.email_label, data.contact_section.email_label_en), name_label: s(data.contact_section.name_label, data.contact_section.name_label_en), name_placeholder: s(data.contact_section.name_placeholder, data.contact_section.name_placeholder_en), phone_field_label: s(data.contact_section.phone_field_label, data.contact_section.phone_field_label_en), phone_placeholder: s(data.contact_section.phone_placeholder, data.contact_section.phone_placeholder_en), note_label: s(data.contact_section.note_label, data.contact_section.note_label_en), note_optional_label: s(data.contact_section.note_optional_label, data.contact_section.note_optional_label_en), note_placeholder: s(data.contact_section.note_placeholder, data.contact_section.note_placeholder_en), submit_label: s(data.contact_section.submit_label, data.contact_section.submit_label_en), sending_label: s(data.contact_section.sending_label, data.contact_section.sending_label_en), success_title: s(data.contact_section.success_title, data.contact_section.success_title_en), success_text: s(data.contact_section.success_text, data.contact_section.success_text_en), success_button_label: s(data.contact_section.success_button_label, data.contact_section.success_button_label_en), }, newsletter: { ...data.newsletter, title: s(data.newsletter.title, data.newsletter.title_en), lead: s(data.newsletter.lead, data.newsletter.lead_en), placeholder: s(data.newsletter.placeholder, data.newsletter.placeholder_en), button_label: s(data.newsletter.button_label, data.newsletter.button_label_en), sending_label: s(data.newsletter.sending_label, data.newsletter.sending_label_en), success_text: s(data.newsletter.success_text, data.newsletter.success_text_en), }, footer: { ...data.footer, about_text: s(data.footer.about_text, data.footer.about_text_en), pages_heading: s(data.footer.pages_heading, data.footer.pages_heading_en), services_heading: s(data.footer.services_heading, data.footer.services_heading_en), contact_heading: s(data.footer.contact_heading, data.footer.contact_heading_en), copyright: s(data.footer.copyright, data.footer.copyright_en), tagline: s(data.footer.tagline, data.footer.tagline_en), socials: list(data.footer.socials, data.footer.socials_en), }, seo_meta: data.seo_meta.map((m) => ({ ...m, title: s(m.title, m.title_en), description: s(m.description, m.description_en), })), } }