From b26207769f5493e943b77a1351d19ddb6c6a16a9 Mon Sep 17 00:00:00 2001 From: aramesh-site deploy Date: Fri, 9 Oct 2026 23:36:55 +0000 Subject: [PATCH] =?UTF-8?q?fix(seo):=20=D8=A7=D9=86=D8=AA=D8=B4=D8=A7?= =?UTF-8?q?=D8=B1=20=D9=85=D8=B4=D8=AE=D8=B5=D8=A7=D8=AA=20=D9=81=D9=86?= =?UTF-8?q?=DB=8C=20=D9=BE=D8=B1=D9=88=DA=98=D9=87=E2=80=8C=D9=87=D8=A7=20?= =?UTF-8?q?=E2=80=94=20=D8=A8=D8=A7=DA=AF=20=D8=AC=D8=A7=D8=A7=D9=81=D8=AA?= =?UTF-8?q?=D8=A7=D8=AF=D9=87=20=DA=A9=D9=87=20=D8=B2=DB=8C=D8=B1=D8=A8?= =?UTF-8?q?=D9=86=D8=A7/=D8=B7=D8=A8=D9=82=D8=A7=D8=AA/=D9=88=D8=A7=D8=AD?= =?UTF-8?q?=D8=AF=D9=87=D8=A7=20=D8=B1=D8=A7=20=D8=AD=D8=B0=D9=81=20=D9=85?= =?UTF-8?q?=DB=8C=E2=80=8C=DA=A9=D8=B1=D8=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit پاسخ به این‌که دستیارهای AI «متراژ پروژه را پیدا نمی‌کنند» در حالی که در پنل ثبت شده است: - _project_content_html فقط ۴ فیلد (موقعیت/سال/زیربنا/کارفرما) را منتشر می‌کرد و زیربنا را روی نسخهٔ انگلیسی به‌خاطر نبود *_en حذف می‌کرد. حالا همهٔ فیلدهای فنی (زمین، زیربنا، طبقات، پیلوت، واحدهای مسکونی/تجاری/اداری، کاربری، نوع، کارفرما، وضعیت) منتشر می‌شوند؛ اعداد زبان‌مستقل‌اند و در نبود ترجمه هم مقدار فارسی می‌آید. - _project_schema: همان مشخصات به‌صورت additionalProperty (PropertyValue) اضافه شد تا به‌عنوان دادهٔ ساخت‌یافته قابل استناد باشد. نمونهٔ زنده (آرامش الیسیان): زمین ۱۵۵۰، زیربنا ۸۷۰۰، طبقات ۷، ۳۱ واحد مسکونی، ۶ تجاری. ۶۵/۶۵ پروژه زیربنا و طبقات دارند — پیش از این هیچ‌کدام منتشر نمی‌شد. --- backend/app/seo_pages.py | 44 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/backend/app/seo_pages.py b/backend/app/seo_pages.py index 6ec12bc..0420882 100644 --- a/backend/app/seo_pages.py +++ b/backend/app/seo_pages.py @@ -1012,6 +1012,25 @@ def _project_schema(project: models.Project, lang: str, db: Session) -> dict: schema["description"] = description if location: schema["locationCreated"] = {"@type": "Place", "name": location.strip()} + # مشخصات فنی پروژه — دادهٔ ساخت‌یافته تا موتورها/دستیارها بتوانند به آن استناد کنند + def spec(fa_v: object, en_v: object, label: str) -> dict | None: + val = (str(en_v).strip() if (lang == "en" and str(en_v or "").strip()) else str(fa_v or "").strip()) + return {"@type": "PropertyValue", "name": label, "value": val} if val else None + + specs = [ + spec(project.year, getattr(project, "year_en", ""), "Year" if lang == "en" else "سال"), + spec(project.location, getattr(project, "location_en", ""), "Location" if lang == "en" else "موقعیت"), + spec(project.land_area, getattr(project, "land_area_en", ""), "Land area" if lang == "en" else "مساحت زمین"), + spec(project.area, getattr(project, "area_en", ""), "Built area" if lang == "en" else "زیربنا"), + spec(project.floors, getattr(project, "floors_en", ""), "Floors" if lang == "en" else "طبقات"), + spec(project.units_residential, getattr(project, "units_residential_en", ""), "Residential units" if lang == "en" else "واحد مسکونی"), + spec(project.units_commercial, getattr(project, "units_commercial_en", ""), "Commercial units" if lang == "en" else "واحد تجاری"), + spec(project.units_office, getattr(project, "units_office_en", ""), "Office units" if lang == "en" else "واحد اداری"), + spec(project.client, getattr(project, "client_en", ""), "Client" if lang == "en" else "کارفرما"), + ] + specs = [s for s in specs if s] + if specs: + schema["additionalProperty"] = specs # همهٔ تصاویر (شاخص + گالری) به‌صورت ImageObject با نام — تا هر تصویر هویت داشته باشد paths = [project.image] if (project.image or "").strip() else [] for g in (project.gallery or []): @@ -1048,13 +1067,30 @@ def _project_content_html(project: models.Project, lang: str, brand: str) -> str parts.append(f"

{esc(text)}

") facts = [] + # مشخصات فنی — همهٔ فیلدهای عدسی که تیم در پنل پر می‌کند. + # اعداد زبان‌مستقل‌اند؛ پس حتی وقتی ترجمهٔ انگلیسی نیست، مقدار فارسی + # (ارقام فارسی) هم منتشر می‌شود تا داده گم نشود. + def num(fa_v: object, en_v: object) -> str: + if lang == "en" and str(en_v or "").strip(): + return str(en_v).strip() + return str(fa_v or "").strip() + for fa_v, en_v, label_fa, label_en in [ - (project.location, project.location_en, "موقعیت", "Location"), - (project.year, project.year_en, "سال", "Year"), - (project.area, getattr(project, "area_en", ""), "زیربنا", "Area"), + (project.location, getattr(project, "location_en", ""), "موقعیت", "Location"), + (project.year, getattr(project, "year_en", ""), "سال", "Year"), + (project.project_type, getattr(project, "project_type_en", ""), "نوع پروژه", "Project type"), + (project.usage, getattr(project, "usage_en", ""), "کاربری", "Usage"), + (project.land_area, getattr(project, "land_area_en", ""), "مساحت زمین (مترمربع)", "Land area (m²)"), + (project.area, getattr(project, "area_en", ""), "زیربنا (مترمربع)", "Built area (m²)"), + (project.floors, getattr(project, "floors_en", ""), "تعداد طبقات", "Floors"), + (project.pilot_floors, getattr(project, "pilot_floors_en", ""), "طبقات پیلوت", "Pilot floors"), + (project.units_residential, getattr(project, "units_residential_en", ""), "واحد مسکونی", "Residential units"), + (project.units_commercial, getattr(project, "units_commercial_en", ""), "واحد تجاری", "Commercial units"), + (project.units_office, getattr(project, "units_office_en", ""), "واحد اداری", "Office units"), (project.client, getattr(project, "client_en", ""), "کارفرما", "Client"), + (project.status, "", "وضعیت", "Status"), ]: - val = en(fa_v or "", en_v) + val = num(fa_v, en_v) if val: facts.append(f"
  • {label_en if lang == 'en' else label_fa}: {esc(val)}
  • ") if facts: