feat: add configurable currency locale and fix vendor JS init
Currency Locale Configuration: - Add platform-level storefront settings (locale, currency) - Create PlatformSettingsService with resolution chain: vendor → AdminSetting → environment → hardcoded fallback - Add storefront_locale nullable field to Vendor model - Update shop routes to resolve and pass locale to templates - Add window.SHOP_CONFIG for frontend JavaScript access - Centralize formatPrice() in shop-layout.js using SHOP_CONFIG - Remove local formatPrice functions from shop templates Vendor JS Bug Fix: - Fix vendorCode being null on all vendor pages - Root cause: page components overriding init() without calling parent - Add parent init call to 14 vendor JS files - Add JS-013 architecture rule to prevent future regressions - Validator now checks vendor JS files for parent init pattern Files changed: - New: app/services/platform_settings_service.py - New: alembic/versions/s7a8b9c0d1e2_add_storefront_locale_to_vendors.py - Modified: 14 vendor JS files, shop templates, validation scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,10 @@ class Vendor(Base, TimestampMixin):
|
||||
JSON, nullable=False, default=["fr", "de", "en"]
|
||||
) # Array of enabled languages for storefront language selector
|
||||
|
||||
# Currency/number formatting locale (e.g., 'fr-LU' = "29,99 €", 'en-GB' = "€29.99")
|
||||
# NULL means inherit from platform default (AdminSetting 'default_storefront_locale')
|
||||
storefront_locale = Column(String(10), nullable=True)
|
||||
|
||||
# ========================================================================
|
||||
# Relationships
|
||||
# ========================================================================
|
||||
|
||||
@@ -81,6 +81,11 @@ class VendorCreate(BaseModel):
|
||||
storefront_languages: list[str] | None = Field(
|
||||
default=["fr", "de", "en"], description="Enabled languages for storefront"
|
||||
)
|
||||
storefront_locale: str | None = Field(
|
||||
None,
|
||||
description="Locale for currency/number formatting (e.g., 'fr-LU', 'de-DE'). NULL = inherit from platform default",
|
||||
max_length=10,
|
||||
)
|
||||
|
||||
@field_validator("subdomain")
|
||||
@classmethod
|
||||
@@ -152,6 +157,11 @@ class VendorUpdate(BaseModel):
|
||||
storefront_languages: list[str] | None = Field(
|
||||
None, description="Enabled languages for storefront"
|
||||
)
|
||||
storefront_locale: str | None = Field(
|
||||
None,
|
||||
description="Locale for currency/number formatting (e.g., 'fr-LU', 'de-DE'). NULL = inherit from platform default",
|
||||
max_length=10,
|
||||
)
|
||||
|
||||
@field_validator("subdomain")
|
||||
@classmethod
|
||||
@@ -197,6 +207,9 @@ class VendorResponse(BaseModel):
|
||||
storefront_language: str = "fr"
|
||||
storefront_languages: list[str] = ["fr", "de", "en"]
|
||||
|
||||
# Currency/number formatting locale (NULL = inherit from platform default)
|
||||
storefront_locale: str | None = None
|
||||
|
||||
# Timestamps
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
Reference in New Issue
Block a user