feat(cms): Phase A — page type selector, translation UI, SEO cleanup
Some checks failed
Some checks failed
Content page editor improvements: - Page type selector: Content Page / Landing Page dropdown (sets template) - Title language tabs: translate page titles per language (same pattern as sections) - Content language tabs: translate page content per language - Meta description language tabs: translatable SEO descriptions - Template-driven section palette: template defines which sections are available (store landing pages hide Pricing, platform homepages show all) - Hide content editor when Landing Page selected, hide sections when Content Page Schema changes (migration cms_003): - Add meta_description_translations column (JSON) to content_pages - Drop meta_keywords column (obsolete, ignored by all search engines since 2009) - Remove meta keywords tag from storefront and platform base templates API + service updates: - title_translations, content_translations, meta_description_translations added to create/update schemas, route handlers, and service methods Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -135,7 +135,12 @@ class ContentPage(Base):
|
||||
|
||||
# SEO
|
||||
meta_description = Column(String(300), nullable=True)
|
||||
meta_keywords = Column(String(300), nullable=True)
|
||||
meta_description_translations = Column(
|
||||
JSON,
|
||||
nullable=True,
|
||||
default=None,
|
||||
comment="Language-keyed meta description dict for multi-language SEO",
|
||||
)
|
||||
|
||||
# Publishing
|
||||
is_published = Column(Boolean, default=False, nullable=False)
|
||||
@@ -230,6 +235,16 @@ class ContentPage(Base):
|
||||
)
|
||||
return self.content
|
||||
|
||||
def get_translated_meta_description(self, lang: str, default_lang: str = "fr") -> str:
|
||||
"""Get meta description in the given language, falling back to default_lang then self.meta_description."""
|
||||
if self.meta_description_translations:
|
||||
return (
|
||||
self.meta_description_translations.get(lang)
|
||||
or self.meta_description_translations.get(default_lang)
|
||||
or self.meta_description or ""
|
||||
)
|
||||
return self.meta_description or ""
|
||||
|
||||
def to_dict(self):
|
||||
"""Convert to dictionary for API responses."""
|
||||
return {
|
||||
@@ -248,7 +263,7 @@ class ContentPage(Base):
|
||||
"template": self.template,
|
||||
"sections": self.sections,
|
||||
"meta_description": self.meta_description,
|
||||
"meta_keywords": self.meta_keywords,
|
||||
"meta_description_translations": self.meta_description_translations,
|
||||
"is_published": self.is_published,
|
||||
"published_at": (
|
||||
self.published_at.isoformat() if self.published_at else None
|
||||
|
||||
Reference in New Issue
Block a user