feat(i18n): add multilingual platform descriptions and HostWizard demo data
Some checks failed
CI / ruff (push) Successful in 11s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

- Add description_translations JSON column to Platform model + migration
- Add language tabs to platform admin edit form for multilingual descriptions
- Update API schemas to include description_translations in request/response
- Translate pricing section UI labels via _t() macro (monthly/annual/CTA/etc.)
- Add Luxembourgish (lb) support to all platforms (OMS, Main, Loyalty, Hosting)
- Seed description_translations, contact emails, and social links for all platforms
- Add LuxWeb Agency demo merchant with hosting stores, team, and content pages
- Fix language code typo: lu → lb in platform-edit.js availableLanguages
- Fix store content pages to use correct primary platform instead of hardcoded OMS

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 23:38:52 +01:00
parent 2268f32f51
commit 820ab1aaa4
8 changed files with 327 additions and 32 deletions

View File

@@ -11,7 +11,7 @@
#}
{# Helper macro: resolve a TranslatableText field with fallback #}
{% macro _t(field, fallback='') %}
{% macro _t(field, lang, default_lang, fallback='') %}
{%- if field and field.translations -%}
{{ field.translations.get(lang) or field.translations.get(default_lang) or fallback }}
{%- else -%}
@@ -25,12 +25,12 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{# Section header #}
<div class="text-center mb-12">
{% set title = _t(pricing.title, 'Simple, Transparent Pricing') %}
{% set title = _t(pricing.title, lang, default_lang, 'Simple, Transparent Pricing') %}
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
{{ title }}
</h2>
{% set subtitle = _t(pricing.subtitle) %}
{% set subtitle = _t(pricing.subtitle, lang, default_lang) %}
{% if subtitle|trim %}
<p class="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
{{ subtitle }}
@@ -40,13 +40,13 @@
{# Pricing toggle (monthly/annual) #}
{% if pricing.use_subscription_tiers and tiers %}
{% set monthly_label = _t(pricing.monthly_label, 'Monthly') %}
{% set annual_label = _t(pricing.annual_label, 'Annual') %}
{% set save_text = _t(pricing.save_text, 'Save 2 months!') %}
{% set popular_badge = _t(pricing.popular_badge, 'Most Popular') %}
{% set cta_text = _t(pricing.cta_text, 'Start Free Trial') %}
{% set per_month = _t(pricing.per_month_label, '/month') %}
{% set per_year = _t(pricing.per_year_label, '/year') %}
{% set monthly_label = _t(pricing.monthly_label, lang, default_lang, 'Monthly') %}
{% set annual_label = _t(pricing.annual_label, lang, default_lang, 'Annual') %}
{% set save_text = _t(pricing.save_text, lang, default_lang, 'Save 2 months!') %}
{% set popular_badge = _t(pricing.popular_badge, lang, default_lang, 'Most Popular') %}
{% set cta_text = _t(pricing.cta_text, lang, default_lang, 'Start Free Trial') %}
{% set per_month = _t(pricing.per_month_label, lang, default_lang, '/month') %}
{% set per_year = _t(pricing.per_year_label, lang, default_lang, '/year') %}
<div x-data="{ annual: false }" class="space-y-8">
{# Billing toggle #}
@@ -128,7 +128,7 @@
</div>
{% else %}
{# Placeholder when no tiers available #}
{% set coming_soon = _t(pricing.coming_soon_text, 'Pricing plans coming soon') %}
{% set coming_soon = _t(pricing.coming_soon_text, lang, default_lang, 'Pricing plans coming soon') %}
<div class="text-center text-gray-500 dark:text-gray-400 py-8">
{{ coming_soon }}
</div>