feat(i18n): complete post-launch i18n phases 5-8
Some checks failed
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 12s
CI / pytest (push) Failing after 47m21s
CI / validate (push) Successful in 25s

- Phase 5: Translate homepage-modern.html (~90 new locale keys, all
  hardcoded strings replaced with _() calls for dashboard mock,
  features, pricing tiers, testimonial sections)
- Phase 6: Translate homepage-minimal.html (17 new locale keys for
  fallback content, features, and CTA sections)
- Phase 7: Add multi-language page.title/content support with
  title_translations and content_translations JSON columns, Alembic
  migration cms_002, translated title/content resolution in templates,
  and seed script updates with tt() helper
- Phase 8: Complete lb.json audit — fill 6 missing keys (messages,
  confirmations), also backfill same keys in fr.json and de.json

All 4 locale files now have 340 keys with full parity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-03 05:50:06 +01:00
parent 05c53e1865
commit b8aa484653
16 changed files with 965 additions and 235 deletions

View File

@@ -2,7 +2,7 @@
{# 3-Step Signup Wizard: Plan → Account → Payment #}
{% extends "platform/base.html" %}
{% block title %}Start Your Free Trial - Orion{% endblock %}
{% block title %}{{ _("cms.platform.signup.page_title") }} - {{ platform.name if platform else 'Orion' }}{% endblock %}
{% block extra_head %}
{# Stripe.js for payment #}
@@ -16,7 +16,7 @@
{# Progress Steps #}
<div class="mb-12">
<div class="flex items-center justify-between">
<template x-for="(stepName, index) in ['Select Plan', 'Account', 'Payment']" :key="index">
<template x-for="(stepName, index) in ['{{ _("cms.platform.signup.step_plan") }}', '{{ _("cms.platform.signup.step_account") }}', '{{ _("cms.platform.signup.step_payment") }}']" :key="index">
<div class="flex items-center" :class="index < 2 ? 'flex-1' : ''">
<div class="flex items-center justify-center w-10 h-10 rounded-full font-semibold transition-colors"
:class="currentStep > index + 1 ? 'bg-green-500 text-white' : currentStep === index + 1 ? 'bg-indigo-600 text-white' : 'bg-gray-200 dark:bg-gray-700 text-gray-500'">
@@ -50,11 +50,11 @@
STEP 1: SELECT PLAN
=============================================================== #}
<div x-show="currentStep === 1" class="p-8">
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6">Choose Your Plan</h2>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-6">{{ _("cms.platform.signup.choose_plan") }}</h2>
{# Billing Toggle #}
<div class="flex items-center justify-center mb-8 space-x-4">
<span :class="!isAnnual ? 'font-semibold text-gray-900 dark:text-white' : 'text-gray-500'">Monthly</span>
<span :class="!isAnnual ? 'font-semibold text-gray-900 dark:text-white' : 'text-gray-500'">{{ _("cms.platform.pricing.monthly") }}</span>
<button @click="isAnnual = !isAnnual"
class="relative w-12 h-6 rounded-full transition-colors"
:class="isAnnual ? 'bg-indigo-600' : 'bg-gray-300'">
@@ -62,7 +62,7 @@
:class="isAnnual ? 'translate-x-6' : ''"></span>
</button>
<span :class="isAnnual ? 'font-semibold text-gray-900 dark:text-white' : 'text-gray-500'">
Annual <span class="text-green-600 text-xs">Save 17%</span>
{{ _("cms.platform.pricing.annual") }} <span class="text-green-600 text-xs">{{ _("cms.platform.signup.save_percent", percent=17) }}</span>
</span>
</div>
@@ -80,17 +80,17 @@
<div>
<h3 class="font-semibold text-gray-900 dark:text-white">{{ tier.name }}</h3>
<p class="text-sm text-gray-500">
{% if tier.orders_per_month %}{{ tier.orders_per_month }} orders/mo{% else %}Unlimited{% endif %}
{% if tier.orders_per_month %}{{ tier.orders_per_month }} {{ _("cms.platform.signup.orders_per_month") }}{% else %}{{ _("cms.platform.signup.unlimited") }}{% endif %}
&bull;
{% if tier.team_members %}{{ tier.team_members }} user{% if tier.team_members > 1 %}s{% endif %}{% else %}Unlimited{% endif %}
{% if tier.team_members %}{{ tier.team_members }} {{ _("cms.platform.signup.team_members", count=tier.team_members) }}{% else %}{{ _("cms.platform.signup.unlimited") }}{% endif %}
</p>
</div>
<div class="text-right">
<template x-if="!isAnnual">
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ tier.price_monthly|int }}&euro;/mo</span>
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ tier.price_monthly|int }}&euro;{{ _("cms.platform.signup.per_month_short") }}</span>
</template>
<template x-if="isAnnual">
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ ((tier.price_annual or tier.price_monthly * 12) / 12)|round(0)|int }}&euro;/mo</span>
<span class="text-xl font-bold text-gray-900 dark:text-white">{{ ((tier.price_annual or tier.price_monthly * 12) / 12)|round(0)|int }}&euro;{{ _("cms.platform.signup.per_month_short") }}</span>
</template>
</div>
</div>
@@ -103,15 +103,15 @@
{# Free Trial Note #}
<div class="mt-6 p-4 bg-green-50 dark:bg-green-900/20 rounded-xl">
<p class="text-sm text-green-800 dark:text-green-300">
<strong>{{ trial_days }}-day free trial.</strong>
We'll collect your payment info, but you won't be charged until the trial ends.
<strong>{{ trial_days }}-{{ _("cms.platform.signup.trial_info_days") }}</strong>
{{ _("cms.platform.signup.trial_info") }}
</p>
</div>
<button @click="startSignup()"
:disabled="!selectedTier || loading"
class="mt-8 w-full py-3 bg-indigo-600 hover:bg-indigo-700 text-white font-semibold rounded-xl transition-colors disabled:opacity-50">
Continue
{{ _("cms.platform.signup.continue") }}
</button>
</div>
@@ -119,23 +119,23 @@
STEP 2: CREATE ACCOUNT
=============================================================== #}
<div x-show="currentStep === 2" class="p-8">
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">Create Your Account</h2>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.signup.create_account") }}</h2>
<p class="text-sm text-gray-500 dark:text-gray-400 mb-6">
<span class="text-red-500">*</span> Required fields
<span class="text-red-500">*</span> {{ _("cms.platform.signup.required_fields") }}
</p>
<div class="space-y-4">
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
First Name <span class="text-red-500">*</span>
{{ _("cms.platform.signup.first_name") }} <span class="text-red-500">*</span>
</label>
<input type="text" x-model="account.firstName" required
class="w-full px-4 py-3 rounded-xl border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white"/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Last Name <span class="text-red-500">*</span>
{{ _("cms.platform.signup.last_name") }} <span class="text-red-500">*</span>
</label>
<input type="text" x-model="account.lastName" required
class="w-full px-4 py-3 rounded-xl border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white"/>
@@ -144,7 +144,7 @@
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Business Name <span class="text-red-500">*</span>
{{ _("cms.platform.signup.merchant_name") }} <span class="text-red-500">*</span>
</label>
<input type="text" x-model="account.merchantName" required
class="w-full px-4 py-3 rounded-xl border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white"/>
@@ -152,7 +152,7 @@
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email <span class="text-red-500">*</span>
{{ _("cms.platform.signup.email") }} <span class="text-red-500">*</span>
</label>
<input type="email" x-model="account.email" required
class="w-full px-4 py-3 rounded-xl border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white"/>
@@ -160,11 +160,11 @@
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Password <span class="text-red-500">*</span>
{{ _("cms.platform.signup.password") }} <span class="text-red-500">*</span>
</label>
<input type="password" x-model="account.password" required minlength="8"
class="w-full px-4 py-3 rounded-xl border border-gray-300 dark:border-gray-600 bg-gray-50 dark:bg-gray-900 text-gray-900 dark:text-white"/>
<p class="text-xs text-gray-500 mt-1">Minimum 8 characters</p>
<p class="text-xs text-gray-500 mt-1">{{ _("cms.platform.signup.password_hint") }}</p>
</div>
<template x-if="accountError">
@@ -177,12 +177,12 @@
<div class="mt-8 flex gap-4">
<button @click="currentStep = 1"
class="flex-1 py-3 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 font-semibold rounded-xl">
Back
{{ _("cms.platform.signup.back") }}
</button>
<button @click="createAccount()"
:disabled="loading || !isAccountValid()"
class="flex-1 py-3 bg-indigo-600 hover:bg-indigo-700 text-white font-semibold rounded-xl disabled:opacity-50">
Continue to Payment
{{ _("cms.platform.signup.continue_payment") }}
</button>
</div>
</div>
@@ -191,8 +191,8 @@
STEP 3: PAYMENT
=============================================================== #}
<div x-show="currentStep === 3" class="p-8">
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">Add Payment Method</h2>
<p class="text-gray-600 dark:text-gray-400 mb-6">You won't be charged until your {{ trial_days }}-day trial ends.</p>
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.signup.add_payment") }}</h2>
<p class="text-gray-600 dark:text-gray-400 mb-6">{{ _("cms.platform.signup.no_charge_note", trial_days=trial_days) }}</p>
{# Stripe Card Element #}
<div id="card-element" class="p-4 border border-gray-300 dark:border-gray-600 rounded-xl bg-gray-50 dark:bg-gray-900"></div>
@@ -201,16 +201,16 @@
<div class="mt-8 flex gap-4">
<button @click="currentStep = 2"
class="flex-1 py-3 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 font-semibold rounded-xl">
Back
{{ _("cms.platform.signup.back") }}
</button>
<button @click="submitPayment()"
:disabled="loading || paymentProcessing"
class="flex-1 py-3 bg-green-600 hover:bg-green-700 text-white font-semibold rounded-xl disabled:opacity-50">
<template x-if="paymentProcessing">
<span>Processing...</span>
<span>{{ _("cms.platform.signup.processing") }}</span>
</template>
<template x-if="!paymentProcessing">
<span>Start Free Trial</span>
<span>{{ _("cms.platform.signup.start_trial") }}</span>
</template>
</button>
</div>
@@ -224,6 +224,13 @@
{% block extra_scripts %}
<script>
function signupWizard() {
const MSGS = {
failedStart: '{{ _("cms.platform.signup.error_start") }}',
failedAccount: '{{ _("cms.platform.signup.error_account") }}',
paymentNotConfigured: '{{ _("cms.platform.signup.error_payment_config") }}',
paymentFailed: '{{ _("cms.platform.signup.error_payment") }}',
};
return {
currentStep: 1,
loading: false,
@@ -286,11 +293,11 @@ function signupWizard() {
this.sessionId = data.session_id;
this.currentStep = 2;
} else {
alert(data.detail || 'Failed to start signup');
alert(data.detail || MSGS.failedStart);
}
} catch (error) {
console.error('Error:', error);
alert('Failed to start signup. Please try again.');
alert(MSGS.failedStart);
} finally {
this.loading = false;
}
@@ -326,11 +333,11 @@ function signupWizard() {
if (response.ok) {
this.currentStep = 3;
} else {
this.accountError = data.detail || 'Failed to create account';
this.accountError = data.detail || MSGS.failedAccount;
}
} catch (error) {
console.error('Error:', error);
this.accountError = 'Failed to create account. Please try again.';
this.accountError = MSGS.failedAccount;
} finally {
this.loading = false;
}
@@ -379,7 +386,7 @@ function signupWizard() {
async submitPayment() {
if (!this.stripe || !this.clientSecret) {
alert('Payment not configured. Please contact support.');
alert(MSGS.paymentNotConfigured);
return;
}
@@ -416,11 +423,11 @@ function signupWizard() {
}
window.location.href = '/signup/success?store_code=' + data.store_code;
} else {
alert(data.detail || 'Failed to complete signup');
alert(data.detail || MSGS.paymentFailed);
}
} catch (error) {
console.error('Payment error:', error);
alert('Payment failed. Please try again.');
alert(MSGS.paymentFailed);
} finally {
this.paymentProcessing = false;
}

View File

@@ -102,7 +102,8 @@
"signup_without": "Ohne Letzshop registrieren",
"looking_up": "Suche Ihren Shop...",
"found": "Gefunden:",
"claimed_badge": "Bereits beansprucht"
"claimed_badge": "Bereits beansprucht",
"error_lookup": "Suche fehlgeschlagen. Bitte versuchen Sie es erneut."
},
"signup": {
"step_plan": "Plan wählen",
@@ -130,7 +131,18 @@
"no_charge_note": "Sie werden erst nach Ablauf Ihrer {trial_days}-tägigen Testphase belastet.",
"processing": "Verarbeitung...",
"start_trial": "Kostenlose Testversion starten",
"creating_account": "Erstelle Ihr Konto..."
"creating_account": "Erstelle Ihr Konto...",
"page_title": "Starten Sie Ihre kostenlose Testversion",
"required_fields": "Pflichtfelder",
"trial_info_days": "-Tage kostenlose Testversion.",
"error_start": "Anmeldung konnte nicht gestartet werden. Bitte versuchen Sie es erneut.",
"error_account": "Konto konnte nicht erstellt werden. Bitte versuchen Sie es erneut.",
"error_payment_config": "Zahlung nicht konfiguriert. Bitte kontaktieren Sie den Support.",
"error_payment": "Zahlung fehlgeschlagen. Bitte versuchen Sie es erneut.",
"orders_per_month": "Bestellungen/Mo.",
"unlimited": "Unbegrenzt",
"team_members": "Benutzer",
"per_month_short": "/Mo."
},
"success": {
"title": "Willkommen bei Orion!",
@@ -152,6 +164,17 @@
"subtitle": "Schließen Sie sich Letzshop-Händlern an, die Orion für ihre Bestellverwaltung vertrauen. Starten Sie heute Ihre {trial_days}-tägige kostenlose Testversion.",
"button": "Kostenlos testen"
},
"content_page": {
"home": "Startseite",
"published": "Veröffentlicht am",
"last_updated": "Zuletzt aktualisiert:",
"cta_about_title": "Bereit loszulegen?",
"cta_contact_title": "Haben Sie Fragen?",
"cta_about_subtitle": "Schließen Sie sich Tausenden von Shops an, die bereits auf unserer Plattform verkaufen",
"cta_contact_subtitle": "Unser Team ist hier, um Ihnen zum Erfolg zu verhelfen",
"cta_about_button": "Vertrieb kontaktieren",
"cta_contact_button": "Senden Sie uns eine Nachricht"
},
"footer": {
"tagline": "Leichtes OMS für Letzshop-Verkäufer. Verwalten Sie Bestellungen, Lager und Rechnungen.",
"quick_links": "Schnelllinks",
@@ -162,7 +185,8 @@
"terms": "Nutzungsbedingungen",
"about": "Über uns",
"faq": "FAQ",
"contact_us": "Kontaktieren Sie uns"
"contact_us": "Kontaktieren Sie uns",
"all_rights_reserved": "Alle Rechte vorbehalten."
},
"modern": {
"badge_integration": "Offizielle Integration",
@@ -197,7 +221,115 @@
"features_subtitle": "Die operativen Tools, die Letzshop nicht bietet",
"cta_final_title": "Bereit, die Kontrolle über Ihr Letzshop-Geschäft zu übernehmen?",
"cta_final_subtitle": "Schließen Sie sich luxemburgischen Händlern an, die aufgehört haben, gegen Tabellenkalkulationen zu kämpfen, und begonnen haben, ihr Geschäft auszubauen.",
"cta_final_note": "Keine Kreditkarte erforderlich. Einrichtung in 5 Minuten. Volle Professional-Funktionen während der Testphase."
"cta_final_note": "Keine Kreditkarte erforderlich. Einrichtung in 5 Minuten. Volle Professional-Funktionen während der Testphase.",
"page_title": "Orion - Das Back-Office für Letzshop-Verkäufer",
"features_badge": "Funktionen",
"dashboard_title": "Orion Dashboard",
"todays_orders": "Heutige Bestellungen",
"revenue": "Umsatz",
"low_stock": "Geringer Bestand",
"items_need_restock": "Artikel nachbestellen",
"recent_orders": "Aktuelle Bestellungen von Letzshop",
"confirmed": "Bestätigt",
"shipped": "Versendet",
"feat_order_sync": "Automatische Bestellsynchronisation",
"feat_order_sync_desc": "Bestellungen von Letzshop erscheinen sofort. Bestätigen und Tracking-Nummern automatisch synchronisieren.",
"feat_order_sync_1": "Echtzeit-Synchronisation",
"feat_order_sync_2": "Bestätigung mit einem Klick",
"feat_order_sync_3": "Tracking-Nummern-Synchronisation",
"feat_inventory": "Echte Lagerverwaltung",
"feat_inventory_desc": "Eine einzige Wahrheitsquelle für alle Bestände. Lagerorte, Reservierungen und eingehende Bestandsverfolgung.",
"feat_inventory_1": "Produktlagerorte (Fächer)",
"feat_inventory_2": "Bestandsreservierungen",
"feat_inventory_3": "Niedrigbestand-Warnungen",
"feat_invoicing": "Intelligente MwSt-Rechnungsstellung",
"feat_invoicing_desc": "PDF-Rechnungen mit korrekten MwSt-Sätzen erstellen. Luxemburg, EU-Länder, B2B-Reverse-Charge.",
"feat_invoicing_1": "Luxemburg 17% MwSt",
"feat_invoicing_2": "EU-Bestimmungsland-MwSt (OSS)",
"feat_invoicing_3": "B2B-Reverse-Charge",
"feat_customers": "Besitzen Sie Ihre Kunden",
"feat_customers_desc": "Alle Kundendaten in Ihrer Datenbank. Export zu Mailchimp für Marketingkampagnen.",
"feat_customers_1": "Bestellhistorie pro Kunde",
"feat_customers_2": "Lebenszeitwert-Tracking",
"feat_customers_3": "CSV-Export für Marketing",
"feat_team": "Teamverwaltung",
"feat_team_desc": "Laden Sie Teammitglieder mit rollenbasierten Berechtigungen ein. Alle arbeiten von einem Dashboard.",
"feat_team_1": "Mehrere Benutzer",
"feat_team_2": "Rollenbasierter Zugang",
"feat_team_3": "Aktivitätsprotokoll",
"feat_purchase_orders": "Bestellungen",
"feat_purchase_orders_desc": "Verfolgen Sie eingehende Bestände von Lieferanten. Wissen Sie, was bestellt ist und wann es ankommt.",
"feat_purchase_orders_1": "Lieferantenbestellungen verfolgen",
"feat_purchase_orders_2": "Voraussichtliche Ankunftsdaten",
"feat_purchase_orders_3": "Empfang und Bestandsaktualisierung",
"pricing_badge": "Preise",
"pricing_title": "Einfache, transparente Preisgestaltung",
"pricing_subtitle": "Keine Gebühren pro Bestellung. Keine versteckten Kosten. Fester Monatstarif.",
"pricing_per_month": "/Monat",
"pricing_trial_note": "Alle Pläne beinhalten eine 14-tägige kostenlose Testphase. Keine Kreditkarte erforderlich.",
"tier_essential": "Essential",
"tier_essential_desc": "Für Solo-Shops am Anfang",
"tier_essential_price": "49 EUR",
"tier_essential_feat_1": "100 Bestellungen/Monat",
"tier_essential_feat_2": "200 Produkte",
"tier_essential_feat_3": "Luxemburg MwSt-Rechnungen",
"tier_essential_feat_4": "1 Teammitglied",
"tier_essential_cta": "Kostenlos testen",
"tier_professional": "Professional",
"tier_professional_desc": "Für wachsende Multichannel-Verkäufer",
"tier_professional_price": "99 EUR",
"tier_professional_badge": "AM BELIEBTESTEN",
"tier_professional_feat_1": "500 Bestellungen/Monat",
"tier_professional_feat_2": "Unbegrenzte Produkte",
"tier_professional_feat_3": "EU MwSt-Rechnungen",
"tier_professional_feat_4": "Produktlagerorte",
"tier_professional_feat_5": "Bestellungen",
"tier_professional_feat_6": "Kundenexport",
"tier_professional_feat_7": "3 Teammitglieder",
"tier_professional_cta": "Kostenlos testen",
"tier_business": "Business",
"tier_business_desc": "Für Großvolumen-Betriebe",
"tier_business_price": "199 EUR",
"tier_business_feat_1": "2.000 Bestellungen/Monat",
"tier_business_feat_2": "Alles in Professional",
"tier_business_feat_3": "Analyse-Dashboard",
"tier_business_feat_4": "API-Zugang",
"tier_business_feat_5": "Buchhaltungsexport",
"tier_business_feat_6": "10 Teammitglieder",
"tier_business_cta": "Kostenlos testen",
"tier_enterprise": "Enterprise",
"tier_enterprise_desc": "Für große Betriebe und Agenturen",
"tier_enterprise_price": "399+ EUR",
"tier_enterprise_feat_1": "Unbegrenzte Bestellungen",
"tier_enterprise_feat_2": "Alles in Business",
"tier_enterprise_feat_3": "White-Label-Option",
"tier_enterprise_feat_4": "Individuelle Integrationen",
"tier_enterprise_feat_5": "99,9% SLA",
"tier_enterprise_feat_6": "Dedizierter Support",
"tier_enterprise_cta": "Vertrieb kontaktieren",
"testimonial_badge": "Für Luxemburg entwickelt",
"testimonial_quote": "Endlich ein Tool, das versteht, was Letzshop-Verkäufer wirklich brauchen. Keine Tabellenkalkulationen mehr, keine MwSt-Kopfschmerzen mehr.",
"testimonial_name": "Marie L.",
"testimonial_location": "Letzshop Store, Luxemburg-Stadt",
"cta_final_trial": "Starten Sie Ihre 14-tägige kostenlose Testphase"
},
"minimal": {
"page_title_fallback": "Startseite",
"marketplace_suffix": "Marktplatz",
"fallback_title_1": "Multi-Store",
"fallback_title_2": "Marktplatz",
"fallback_subtitle": "Der einfachste Weg, Ihren Online-Shop zu starten und sich mit Kunden weltweit zu verbinden.",
"get_started": "Loslegen",
"feat_fast": "Schnell",
"feat_fast_desc": "Blitzschnelle Leistung, optimiert für Conversions",
"feat_secure": "Sicher",
"feat_secure_desc": "Sicherheit auf Enterprise-Niveau für Ihre Sicherheit",
"feat_custom": "Individuell",
"feat_custom_desc": "Vollständig anpassbar an Ihre Markenidentität",
"cta_title": "Bereit zum Start?",
"cta_subtitle": "Treten Sie noch heute unserem Marktplatz bei",
"cta_contact": "Kontakt",
"cta_learn_more": "Mehr erfahren"
}
},
"features": {
@@ -246,5 +378,15 @@
"manage_media_desc": "Mediendateien hochladen, bearbeiten und löschen",
"manage_themes": "Themes verwalten",
"manage_themes_desc": "Shop-Themes konfigurieren und anpassen"
},
"messages": {
"failed_to_delete_page": "Seite konnte nicht gelöscht werden: {error}",
"media_updated_successfully": "Medium erfolgreich aktualisiert",
"media_deleted_successfully": "Medium erfolgreich gelöscht",
"url_copied_to_clipboard": "URL in die Zwischenablage kopiert",
"failed_to_copy_url": "URL konnte nicht kopiert werden"
},
"confirmations": {
"delete_file": "Sind Sie sicher, dass Sie diese Datei löschen möchten? Dies kann nicht rückgängig gemacht werden."
}
}

View File

@@ -102,7 +102,8 @@
"signup_without": "Sign Up Without Letzshop",
"looking_up": "Looking up your shop...",
"found": "Found:",
"claimed_badge": "Already Claimed"
"claimed_badge": "Already Claimed",
"error_lookup": "Failed to lookup. Please try again."
},
"signup": {
"step_plan": "Select Plan",
@@ -130,7 +131,18 @@
"no_charge_note": "You won't be charged until your {trial_days}-day trial ends.",
"processing": "Processing...",
"start_trial": "Start Free Trial",
"creating_account": "Creating your account..."
"creating_account": "Creating your account...",
"page_title": "Start Your Free Trial",
"required_fields": "Required fields",
"trial_info_days": "day free trial.",
"error_start": "Failed to start signup. Please try again.",
"error_account": "Failed to create account. Please try again.",
"error_payment_config": "Payment not configured. Please contact support.",
"error_payment": "Payment failed. Please try again.",
"orders_per_month": "orders/mo",
"unlimited": "Unlimited",
"team_members": "users",
"per_month_short": "/mo"
},
"success": {
"title": "Welcome to Orion!",
@@ -152,6 +164,17 @@
"subtitle": "Join Letzshop stores who trust Orion for their order management. Start your {trial_days}-day free trial today.",
"button": "Start Free Trial"
},
"content_page": {
"home": "Home",
"published": "Published",
"last_updated": "Last updated:",
"cta_about_title": "Ready to Get Started?",
"cta_contact_title": "Have Questions?",
"cta_about_subtitle": "Join thousands of stores already selling on our platform",
"cta_contact_subtitle": "Our team is here to help you succeed",
"cta_about_button": "Contact Sales",
"cta_contact_button": "Send Us a Message"
},
"footer": {
"tagline": "Lightweight OMS for Letzshop sellers. Manage orders, inventory, and invoicing.",
"quick_links": "Quick Links",
@@ -162,7 +185,8 @@
"terms": "Terms of Service",
"about": "About Us",
"faq": "FAQ",
"contact_us": "Contact Us"
"contact_us": "Contact Us",
"all_rights_reserved": "All rights reserved."
},
"modern": {
"badge_integration": "Official Integration",
@@ -197,7 +221,115 @@
"features_subtitle": "The operational tools Letzshop doesn't provide",
"cta_final_title": "Ready to Take Control of Your Letzshop Business?",
"cta_final_subtitle": "Join Luxembourg stores who've stopped fighting spreadsheets and started growing their business.",
"cta_final_note": "No credit card required. Setup in 5 minutes. Full Professional features during trial."
"cta_final_note": "No credit card required. Setup in 5 minutes. Full Professional features during trial.",
"page_title": "Orion - The Back-Office for Letzshop Sellers",
"features_badge": "Features",
"dashboard_title": "Orion Dashboard",
"todays_orders": "Today's Orders",
"revenue": "Revenue",
"low_stock": "Low Stock",
"items_need_restock": "items need restock",
"recent_orders": "Recent Orders from Letzshop",
"confirmed": "Confirmed",
"shipped": "Shipped",
"feat_order_sync": "Automatic Order Sync",
"feat_order_sync_desc": "Orders from Letzshop appear instantly. Confirm orders and sync tracking numbers back automatically.",
"feat_order_sync_1": "Real-time sync",
"feat_order_sync_2": "One-click confirmation",
"feat_order_sync_3": "Tracking number sync",
"feat_inventory": "Real Inventory Management",
"feat_inventory_desc": "One source of truth for all stock. Locations, reservations, and incoming stock tracking.",
"feat_inventory_1": "Product locations (bins)",
"feat_inventory_2": "Stock reservations",
"feat_inventory_3": "Low stock alerts",
"feat_invoicing": "Smart VAT Invoicing",
"feat_invoicing_desc": "Generate PDF invoices with correct VAT rates. Luxembourg, EU countries, B2B reverse charge.",
"feat_invoicing_1": "Luxembourg 17% VAT",
"feat_invoicing_2": "EU destination VAT (OSS)",
"feat_invoicing_3": "B2B reverse charge",
"feat_customers": "Own Your Customers",
"feat_customers_desc": "All customer data in your database. Export to Mailchimp for marketing campaigns.",
"feat_customers_1": "Order history per customer",
"feat_customers_2": "Lifetime value tracking",
"feat_customers_3": "CSV export for marketing",
"feat_team": "Team Management",
"feat_team_desc": "Invite team members with role-based permissions. Everyone works from one dashboard.",
"feat_team_1": "Multiple users",
"feat_team_2": "Role-based access",
"feat_team_3": "Activity logging",
"feat_purchase_orders": "Purchase Orders",
"feat_purchase_orders_desc": "Track incoming stock from suppliers. Know what's on order and when it arrives.",
"feat_purchase_orders_1": "Track supplier orders",
"feat_purchase_orders_2": "Expected arrival dates",
"feat_purchase_orders_3": "Receive and update stock",
"pricing_badge": "Pricing",
"pricing_title": "Simple, Transparent Pricing",
"pricing_subtitle": "No per-order fees. No hidden costs. Flat monthly rate.",
"pricing_per_month": "/month",
"pricing_trial_note": "All plans include a 14-day free trial. No credit card required.",
"tier_essential": "Essential",
"tier_essential_desc": "For solo stores getting started",
"tier_essential_price": "EUR 49",
"tier_essential_feat_1": "100 orders/month",
"tier_essential_feat_2": "200 products",
"tier_essential_feat_3": "Luxembourg VAT invoices",
"tier_essential_feat_4": "1 team member",
"tier_essential_cta": "Start Free Trial",
"tier_professional": "Professional",
"tier_professional_desc": "For growing multi-channel sellers",
"tier_professional_price": "EUR 99",
"tier_professional_badge": "MOST POPULAR",
"tier_professional_feat_1": "500 orders/month",
"tier_professional_feat_2": "Unlimited products",
"tier_professional_feat_3": "EU VAT invoices",
"tier_professional_feat_4": "Product locations",
"tier_professional_feat_5": "Purchase orders",
"tier_professional_feat_6": "Customer export",
"tier_professional_feat_7": "3 team members",
"tier_professional_cta": "Start Free Trial",
"tier_business": "Business",
"tier_business_desc": "For high-volume operations",
"tier_business_price": "EUR 199",
"tier_business_feat_1": "2,000 orders/month",
"tier_business_feat_2": "Everything in Professional",
"tier_business_feat_3": "Analytics dashboard",
"tier_business_feat_4": "API access",
"tier_business_feat_5": "Accounting export",
"tier_business_feat_6": "10 team members",
"tier_business_cta": "Start Free Trial",
"tier_enterprise": "Enterprise",
"tier_enterprise_desc": "For large operations & agencies",
"tier_enterprise_price": "EUR 399+",
"tier_enterprise_feat_1": "Unlimited orders",
"tier_enterprise_feat_2": "Everything in Business",
"tier_enterprise_feat_3": "White-label option",
"tier_enterprise_feat_4": "Custom integrations",
"tier_enterprise_feat_5": "99.9% SLA",
"tier_enterprise_feat_6": "Dedicated support",
"tier_enterprise_cta": "Contact Sales",
"testimonial_badge": "Built for Luxembourg",
"testimonial_quote": "Finally, a tool that understands what Letzshop sellers actually need. No more spreadsheets, no more VAT headaches.",
"testimonial_name": "Marie L.",
"testimonial_location": "Letzshop Store, Luxembourg City",
"cta_final_trial": "Start Your 14-Day Free Trial"
},
"minimal": {
"page_title_fallback": "Home",
"marketplace_suffix": "Marketplace",
"fallback_title_1": "Multi-Store",
"fallback_title_2": "Marketplace",
"fallback_subtitle": "The simplest way to launch your online store and connect with customers worldwide.",
"get_started": "Get Started",
"feat_fast": "Fast",
"feat_fast_desc": "Lightning-fast performance optimized for conversions",
"feat_secure": "Secure",
"feat_secure_desc": "Enterprise-grade security for your peace of mind",
"feat_custom": "Custom",
"feat_custom_desc": "Fully customizable to match your brand identity",
"cta_title": "Ready to launch?",
"cta_subtitle": "Join our marketplace today",
"cta_contact": "Contact Us",
"cta_learn_more": "Learn More"
}
},
"permissions": {

View File

@@ -102,7 +102,8 @@
"signup_without": "S'inscrire sans Letzshop",
"looking_up": "Recherche de votre boutique...",
"found": "Trouvé :",
"claimed_badge": "Déjà réclamée"
"claimed_badge": "Déjà réclamée",
"error_lookup": "La recherche a échoué. Veuillez réessayer."
},
"signup": {
"step_plan": "Choisir le plan",
@@ -130,7 +131,18 @@
"no_charge_note": "Vous ne serez pas débité avant la fin de votre essai de {trial_days} jours.",
"processing": "Traitement en cours...",
"start_trial": "Démarrer l'essai gratuit",
"creating_account": "Création de votre compte..."
"creating_account": "Création de votre compte...",
"page_title": "Démarrez votre essai gratuit",
"required_fields": "Champs obligatoires",
"trial_info_days": "jours d'essai gratuit.",
"error_start": "Échec du démarrage de l'inscription. Veuillez réessayer.",
"error_account": "Échec de la création du compte. Veuillez réessayer.",
"error_payment_config": "Paiement non configuré. Veuillez contacter le support.",
"error_payment": "Le paiement a échoué. Veuillez réessayer.",
"orders_per_month": "commandes/mois",
"unlimited": "Illimité",
"team_members": "utilisateurs",
"per_month_short": "/mois"
},
"success": {
"title": "Bienvenue sur Orion !",
@@ -152,6 +164,17 @@
"subtitle": "Rejoignez les vendeurs Letzshop qui font confiance à Orion pour leur gestion de commandes. Commencez votre essai gratuit de {trial_days} jours aujourd'hui.",
"button": "Essai gratuit"
},
"content_page": {
"home": "Accueil",
"published": "Publié le",
"last_updated": "Dernière mise à jour :",
"cta_about_title": "Prêt à commencer ?",
"cta_contact_title": "Des questions ?",
"cta_about_subtitle": "Rejoignez des milliers de boutiques qui vendent déjà sur notre plateforme",
"cta_contact_subtitle": "Notre équipe est là pour vous aider à réussir",
"cta_about_button": "Contactez-nous",
"cta_contact_button": "Envoyez-nous un message"
},
"footer": {
"tagline": "OMS léger pour les vendeurs Letzshop. Gérez commandes, stocks et facturation.",
"quick_links": "Liens rapides",
@@ -162,7 +185,8 @@
"terms": "Conditions d'utilisation",
"about": "À propos",
"faq": "FAQ",
"contact_us": "Nous contacter"
"contact_us": "Nous contacter",
"all_rights_reserved": "Tous droits réservés."
},
"modern": {
"badge_integration": "Intégration officielle",
@@ -197,7 +221,115 @@
"features_subtitle": "Les outils opérationnels que Letzshop ne fournit pas",
"cta_final_title": "Prêt à prendre le contrôle de votre entreprise Letzshop ?",
"cta_final_subtitle": "Rejoignez les vendeurs luxembourgeois qui ont arrêté de lutter contre les tableurs et ont commencé à développer leur entreprise.",
"cta_final_note": "Aucune carte de crédit requise. Configuration en 5 minutes. Toutes les fonctionnalités Pro pendant l'essai."
"cta_final_note": "Aucune carte de crédit requise. Configuration en 5 minutes. Toutes les fonctionnalités Pro pendant l'essai.",
"page_title": "Orion - Le back-office pour les vendeurs Letzshop",
"features_badge": "Fonctionnalités",
"dashboard_title": "Tableau de bord Orion",
"todays_orders": "Commandes du jour",
"revenue": "Chiffre d'affaires",
"low_stock": "Stock faible",
"items_need_restock": "articles à réapprovisionner",
"recent_orders": "Commandes récentes de Letzshop",
"confirmed": "Confirmée",
"shipped": "Expédiée",
"feat_order_sync": "Synchronisation automatique des commandes",
"feat_order_sync_desc": "Les commandes Letzshop apparaissent instantanément. Confirmez et synchronisez les numéros de suivi automatiquement.",
"feat_order_sync_1": "Synchronisation en temps réel",
"feat_order_sync_2": "Confirmation en un clic",
"feat_order_sync_3": "Synchronisation des numéros de suivi",
"feat_inventory": "Gestion réelle des stocks",
"feat_inventory_desc": "Une source unique de vérité pour tous les stocks. Emplacements, réservations et suivi des stocks entrants.",
"feat_inventory_1": "Emplacements produits (bacs)",
"feat_inventory_2": "Réservations de stock",
"feat_inventory_3": "Alertes de stock faible",
"feat_invoicing": "Facturation TVA intelligente",
"feat_invoicing_desc": "Générez des factures PDF avec les taux de TVA corrects. Luxembourg, pays UE, autoliquidation B2B.",
"feat_invoicing_1": "TVA Luxembourg 17%",
"feat_invoicing_2": "TVA destination UE (OSS)",
"feat_invoicing_3": "Autoliquidation B2B",
"feat_customers": "Possédez vos clients",
"feat_customers_desc": "Toutes les données clients dans votre base. Exportez vers Mailchimp pour vos campagnes marketing.",
"feat_customers_1": "Historique des commandes par client",
"feat_customers_2": "Suivi de la valeur à vie",
"feat_customers_3": "Export CSV pour le marketing",
"feat_team": "Gestion d'équipe",
"feat_team_desc": "Invitez des membres avec des permissions basées sur les rôles. Tout le monde travaille depuis un tableau de bord.",
"feat_team_1": "Utilisateurs multiples",
"feat_team_2": "Accès basé sur les rôles",
"feat_team_3": "Journal d'activité",
"feat_purchase_orders": "Bons de commande",
"feat_purchase_orders_desc": "Suivez les stocks entrants des fournisseurs. Sachez ce qui est commandé et quand ça arrive.",
"feat_purchase_orders_1": "Suivi des commandes fournisseurs",
"feat_purchase_orders_2": "Dates d'arrivée prévues",
"feat_purchase_orders_3": "Réception et mise à jour du stock",
"pricing_badge": "Tarifs",
"pricing_title": "Tarification simple et transparente",
"pricing_subtitle": "Pas de frais par commande. Pas de coûts cachés. Tarif mensuel fixe.",
"pricing_per_month": "/mois",
"pricing_trial_note": "Tous les plans incluent un essai gratuit de 14 jours. Aucune carte de crédit requise.",
"tier_essential": "Essentiel",
"tier_essential_desc": "Pour les boutiques solo qui débutent",
"tier_essential_price": "49 EUR",
"tier_essential_feat_1": "100 commandes/mois",
"tier_essential_feat_2": "200 produits",
"tier_essential_feat_3": "Factures TVA Luxembourg",
"tier_essential_feat_4": "1 membre d'équipe",
"tier_essential_cta": "Essai gratuit",
"tier_professional": "Professionnel",
"tier_professional_desc": "Pour les vendeurs multicanaux en croissance",
"tier_professional_price": "99 EUR",
"tier_professional_badge": "LE PLUS POPULAIRE",
"tier_professional_feat_1": "500 commandes/mois",
"tier_professional_feat_2": "Produits illimités",
"tier_professional_feat_3": "Factures TVA UE",
"tier_professional_feat_4": "Emplacements produits",
"tier_professional_feat_5": "Bons de commande",
"tier_professional_feat_6": "Export clients",
"tier_professional_feat_7": "3 membres d'équipe",
"tier_professional_cta": "Essai gratuit",
"tier_business": "Business",
"tier_business_desc": "Pour les opérations à haut volume",
"tier_business_price": "199 EUR",
"tier_business_feat_1": "2 000 commandes/mois",
"tier_business_feat_2": "Tout dans Professionnel",
"tier_business_feat_3": "Tableau de bord analytique",
"tier_business_feat_4": "Accès API",
"tier_business_feat_5": "Export comptable",
"tier_business_feat_6": "10 membres d'équipe",
"tier_business_cta": "Essai gratuit",
"tier_enterprise": "Entreprise",
"tier_enterprise_desc": "Pour les grandes opérations et agences",
"tier_enterprise_price": "399+ EUR",
"tier_enterprise_feat_1": "Commandes illimitées",
"tier_enterprise_feat_2": "Tout dans Business",
"tier_enterprise_feat_3": "Option marque blanche",
"tier_enterprise_feat_4": "Intégrations personnalisées",
"tier_enterprise_feat_5": "SLA 99,9%",
"tier_enterprise_feat_6": "Support dédié",
"tier_enterprise_cta": "Contacter les ventes",
"testimonial_badge": "Conçu pour le Luxembourg",
"testimonial_quote": "Enfin, un outil qui comprend ce dont les vendeurs Letzshop ont vraiment besoin. Plus de tableurs, plus de casse-tête TVA.",
"testimonial_name": "Marie L.",
"testimonial_location": "Boutique Letzshop, Luxembourg-Ville",
"cta_final_trial": "Commencez votre essai gratuit de 14 jours"
},
"minimal": {
"page_title_fallback": "Accueil",
"marketplace_suffix": "Marketplace",
"fallback_title_1": "Marketplace",
"fallback_title_2": "Multi-Boutiques",
"fallback_subtitle": "Le moyen le plus simple de lancer votre boutique en ligne et de vous connecter avec des clients du monde entier.",
"get_started": "Commencer",
"feat_fast": "Rapide",
"feat_fast_desc": "Performance ultra-rapide optimisée pour les conversions",
"feat_secure": "Sécurisé",
"feat_secure_desc": "Sécurité de niveau entreprise pour votre tranquillité d'esprit",
"feat_custom": "Personnalisable",
"feat_custom_desc": "Entièrement personnalisable pour correspondre à votre identité de marque",
"cta_title": "Prêt à vous lancer ?",
"cta_subtitle": "Rejoignez notre marketplace aujourd'hui",
"cta_contact": "Contactez-nous",
"cta_learn_more": "En savoir plus"
}
},
"features": {
@@ -246,5 +378,15 @@
"manage_media_desc": "Télécharger, modifier et supprimer les fichiers médias",
"manage_themes": "Gérer les thèmes",
"manage_themes_desc": "Configurer et personnaliser les thèmes"
},
"messages": {
"failed_to_delete_page": "Impossible de supprimer la page : {error}",
"media_updated_successfully": "Média mis à jour avec succès",
"media_deleted_successfully": "Média supprimé avec succès",
"url_copied_to_clipboard": "URL copié dans le presse-papiers",
"failed_to_copy_url": "Impossible de copier l'URL"
},
"confirmations": {
"delete_file": "Êtes-vous sûr de vouloir supprimer ce fichier ? Cette action est irréversible."
}
}

View File

@@ -102,7 +102,8 @@
"signup_without": "Ouni Letzshop registréieren",
"looking_up": "Sich Äre Buttek...",
"found": "Fonnt:",
"claimed_badge": "Scho reklaméiert"
"claimed_badge": "Scho reklaméiert",
"error_lookup": "D'Sich huet feelgeschloen. Probéiert w.e.g. nach eng Kéier."
},
"signup": {
"step_plan": "Plang wielen",
@@ -130,7 +131,18 @@
"no_charge_note": "Dir gitt eréischt nom Enn vun Ärer {trial_days}-Deeg Testperiod belaaschtt.",
"processing": "Veraarbechtung...",
"start_trial": "Gratis Testversioun starten",
"creating_account": "Erstellt Äre Kont..."
"creating_account": "Erstellt Äre Kont...",
"page_title": "Start Är gratis Testversioun",
"required_fields": "Obligatoresch Felder",
"trial_info_days": "-Deeg gratis Testversioun.",
"error_start": "Umeldung konnt net gestart ginn. Probéiert w.e.g. nach eng Kéier.",
"error_account": "Kont konnt net erstallt ginn. Probéiert w.e.g. nach eng Kéier.",
"error_payment_config": "Bezuelung net konfiguréiert. Kontaktéiert w.e.g. de Support.",
"error_payment": "Bezuelung feelgeschloen. Probéiert w.e.g. nach eng Kéier.",
"orders_per_month": "Bestellungen/Mount",
"unlimited": "Onbegrenzt",
"team_members": "Benotzer",
"per_month_short": "/Mount"
},
"success": {
"title": "Wëllkomm bei Orion!",
@@ -152,6 +164,17 @@
"subtitle": "Schléisst Iech Letzshop Händler un déi Orion fir hir Bestellungsverwaltung vertrauen. Fänkt haut Är {trial_days}-Deeg gratis Testversioun un.",
"button": "Gratis Testen"
},
"content_page": {
"home": "Haaptsäit",
"published": "Publizéiert den",
"last_updated": "Lescht aktualiséiert:",
"cta_about_title": "Prett fir unzefänken?",
"cta_contact_title": "Hutt Dir Froen?",
"cta_about_subtitle": "Schléisst Iech Dausende vu Butteker un déi scho op eiser Plattform verkafen",
"cta_contact_subtitle": "Eist Team ass hei fir Iech ze hëllefen",
"cta_about_button": "Kontaktéiert de Verkaf",
"cta_contact_button": "Schéckt eis eng Noriicht"
},
"footer": {
"tagline": "Liichtt OMS fir Letzshop Verkeefer. Verwaltt Bestellungen, Lager an Rechnungen.",
"quick_links": "Séier Linken",
@@ -162,7 +185,8 @@
"terms": "Notzungsbedéngungen",
"about": "Iwwer eis",
"faq": "FAQ",
"contact_us": "Kontaktéiert eis"
"contact_us": "Kontaktéiert eis",
"all_rights_reserved": "All Rechter virbehalen."
},
"modern": {
"badge_integration": "Offiziell Integratioun",
@@ -197,7 +221,115 @@
"features_subtitle": "D'operativ Tools déi Letzshop net bitt",
"cta_final_title": "Prett fir d'Kontroll iwwer Äert Letzshop Geschäft ze iwwerhuelen?",
"cta_final_subtitle": "Schléisst Iech lëtzebuerger Händler un déi opgehalen hunn géint Tabellen ze kämpfen an ugefaang hunn hiert Geschäft auszbauen.",
"cta_final_note": "Keng Kreditkaart néideg. Setup an 5 Minutten. Voll Professional Fonctiounen während der Testperiod."
"cta_final_note": "Keng Kreditkaart néideg. Setup an 5 Minutten. Voll Professional Fonctiounen während der Testperiod.",
"page_title": "Orion - De Back-Office fir Letzshop Verkeefer",
"features_badge": "Fonctiounen",
"dashboard_title": "Orion Dashboard",
"todays_orders": "Bestellunge vun haut",
"revenue": "Ëmsaz",
"low_stock": "Niddrege Bestand",
"items_need_restock": "Artikelen nei beschtellen",
"recent_orders": "Rezent Bestellunge vu Letzshop",
"confirmed": "Confirméiert",
"shipped": "Verschéckt",
"feat_order_sync": "Automatesch Bestellungssynchronisatioun",
"feat_order_sync_desc": "Bestellunge vu Letzshop erschéngen direkt. Confirméiert a synchroniséiert Tracking-Nummeren automatesch.",
"feat_order_sync_1": "Echtzeit-Synchronisatioun",
"feat_order_sync_2": "Confirmatioun mat engem Klick",
"feat_order_sync_3": "Tracking-Nummere Synchronisatioun",
"feat_inventory": "Richteg Lagerverwaltung",
"feat_inventory_desc": "Eng eenzeg Quell vun der Wouerecht fir all Bestänn. Lagerplazen, Reservatiounen an erakommen Bestandsverfolgung.",
"feat_inventory_1": "Produktlagerplazen (Fächer)",
"feat_inventory_2": "Bestandsreservatiounen",
"feat_inventory_3": "Niddreg-Bestand Alarmer",
"feat_invoicing": "Intelligent TVA Rechnungsstellung",
"feat_invoicing_desc": "PDF Rechnunge mat korrekten TVA Sätz erstellen. Lëtzebuerg, EU-Länner, B2B Reverse-Charge.",
"feat_invoicing_1": "Lëtzebuerg 17% TVA",
"feat_invoicing_2": "EU Destinatioun TVA (OSS)",
"feat_invoicing_3": "B2B Reverse-Charge",
"feat_customers": "Besëtzt Är Clienten",
"feat_customers_desc": "All Clientsdaten an Ärer Datebank. Export op Mailchimp fir Marketingcampagnen.",
"feat_customers_1": "Bestellhistoire pro Client",
"feat_customers_2": "Liewen-Zäitwäert Tracking",
"feat_customers_3": "CSV Export fir Marketing",
"feat_team": "Teamverwaltung",
"feat_team_desc": "Invitéiert Teammemberen mat rollbaséierten Berechtigungen. Jiddereen schafft vun engem Dashboard.",
"feat_team_1": "Méi Benotzer",
"feat_team_2": "Rollbaséierten Zougang",
"feat_team_3": "Aktivitéitsprotokoll",
"feat_purchase_orders": "Bestellungen",
"feat_purchase_orders_desc": "Verfolgt erakommen Bestänn vu Fournisseuren. Wësst wat bestallt ass a wéini et ukënnt.",
"feat_purchase_orders_1": "Fournisseur-Bestellunge verfolgen",
"feat_purchase_orders_2": "Erwaart Ukonfts-Datumer",
"feat_purchase_orders_3": "Empfang an Bestandsaktualiséierung",
"pricing_badge": "Präisser",
"pricing_title": "Einfach, transparent Präisgestaltung",
"pricing_subtitle": "Keng Gebühre pro Bestellung. Keng verstoppte Käschten. Feste Monatspräis.",
"pricing_per_month": "/Mount",
"pricing_trial_note": "All Pläng enthale eng 14-Deeg gratis Testperiod. Keng Kreditkaart néideg.",
"tier_essential": "Essential",
"tier_essential_desc": "Fir Solo-Butteker um Ufank",
"tier_essential_price": "49 EUR",
"tier_essential_feat_1": "100 Bestellungen/Mount",
"tier_essential_feat_2": "200 Produkter",
"tier_essential_feat_3": "Lëtzebuerg TVA Rechnungen",
"tier_essential_feat_4": "1 Teammember",
"tier_essential_cta": "Gratis testen",
"tier_professional": "Professional",
"tier_professional_desc": "Fir wuessend Multichannel-Verkeefer",
"tier_professional_price": "99 EUR",
"tier_professional_badge": "AM BELÉIFSTEN",
"tier_professional_feat_1": "500 Bestellungen/Mount",
"tier_professional_feat_2": "Onlimitéiert Produkter",
"tier_professional_feat_3": "EU TVA Rechnungen",
"tier_professional_feat_4": "Produktlagerplazen",
"tier_professional_feat_5": "Bestellungen",
"tier_professional_feat_6": "Clienten-Export",
"tier_professional_feat_7": "3 Teammemberen",
"tier_professional_cta": "Gratis testen",
"tier_business": "Business",
"tier_business_desc": "Fir grouss Volummen Operatiounen",
"tier_business_price": "199 EUR",
"tier_business_feat_1": "2.000 Bestellungen/Mount",
"tier_business_feat_2": "Alles an Professional",
"tier_business_feat_3": "Analyse Dashboard",
"tier_business_feat_4": "API Zougang",
"tier_business_feat_5": "Comptabilitéitsexport",
"tier_business_feat_6": "10 Teammemberen",
"tier_business_cta": "Gratis testen",
"tier_enterprise": "Enterprise",
"tier_enterprise_desc": "Fir grouss Betriber an Agenturen",
"tier_enterprise_price": "399+ EUR",
"tier_enterprise_feat_1": "Onlimitéiert Bestellungen",
"tier_enterprise_feat_2": "Alles an Business",
"tier_enterprise_feat_3": "White-Label Optioun",
"tier_enterprise_feat_4": "Individuell Integratiounen",
"tier_enterprise_feat_5": "99,9% SLA",
"tier_enterprise_feat_6": "Dedizéierten Support",
"tier_enterprise_cta": "Vertrieb kontaktéieren",
"testimonial_badge": "Gemaach fir Lëtzebuerg",
"testimonial_quote": "Endlech en Tool dat versteet wat Letzshop Verkeefer wierklech brauchen. Keng Tabelle méi, keng TVA Kappwéi méi.",
"testimonial_name": "Marie L.",
"testimonial_location": "Letzshop Buttek, Stad Lëtzebuerg",
"cta_final_trial": "Start Är 14-Deeg gratis Testperiod"
},
"minimal": {
"page_title_fallback": "Heempage",
"marketplace_suffix": "Marktplaz",
"fallback_title_1": "Multi-Store",
"fallback_title_2": "Marktplaz",
"fallback_subtitle": "Deen einfachste Wee fir Ären Online-Shop ze starten an Iech mat Clientë weltwäit ze verbannen.",
"get_started": "Ufänken",
"feat_fast": "Séier",
"feat_fast_desc": "Blëtzséier Leeschtung optimiséiert fir Conversiounen",
"feat_secure": "Sécher",
"feat_secure_desc": "Enterprise-Niveau Sécherheet fir Är Gemittlechkeet",
"feat_custom": "Individuell",
"feat_custom_desc": "Komplett personaliséierbar fir zu Ärer Mark ze passen",
"cta_title": "Prett fir ze starten?",
"cta_subtitle": "Trëtt haut eisem Marktplaz bäi",
"cta_contact": "Kontaktéiert eis",
"cta_learn_more": "Méi erfahren"
}
},
"features": {
@@ -246,5 +378,15 @@
"manage_media_desc": "Mediefichieren eroplueden, änneren a läschen",
"manage_themes": "Themes verwalten",
"manage_themes_desc": "Buttek-Themes konfiguréieren an upassen"
},
"messages": {
"failed_to_delete_page": "Konnt d'Säit net läschen: {error}",
"media_updated_successfully": "Medium erfollegräich aktualiséiert",
"media_deleted_successfully": "Medium erfollegräich geläscht",
"url_copied_to_clipboard": "URL an d'Tëschëlag kopéiert",
"failed_to_copy_url": "Konnt den URL net kopéieren"
},
"confirmations": {
"delete_file": "Sidd Dir sécher datt Dir dëse Fichier läsche wëllt? Dat kann net réckgängeg gemaach ginn."
}
}

View File

@@ -0,0 +1,41 @@
"""add title_translations and content_translations to content_pages
Revision ID: cms_002
Revises: cms_001
Create Date: 2026-03-02
"""
import sqlalchemy as sa
from alembic import op
revision = "cms_002"
down_revision = "cms_001"
branch_labels = None
depends_on = None
def upgrade() -> None:
op.add_column(
"content_pages",
sa.Column(
"title_translations",
sa.JSON(),
nullable=True,
comment="Language-keyed title dict for multi-language support",
),
)
op.add_column(
"content_pages",
sa.Column(
"content_translations",
sa.JSON(),
nullable=True,
comment="Language-keyed content dict for multi-language support",
),
)
def downgrade() -> None:
op.drop_column("content_pages", "content_translations")
op.drop_column("content_pages", "title_translations")

View File

@@ -118,6 +118,21 @@ class ContentPage(Base):
comment="Structured homepage sections (hero, features, pricing, cta) with i18n",
)
# Multi-language title and content (JSON dicts keyed by language code)
# e.g. {"en": "About Us", "fr": "À propos", "de": "Über uns", "lb": "Iwwer eis"}
title_translations = Column(
JSON,
nullable=True,
default=None,
comment="Language-keyed title dict for multi-language support",
)
content_translations = Column(
JSON,
nullable=True,
default=None,
comment="Language-keyed content dict for multi-language support",
)
# SEO
meta_description = Column(String(300), nullable=True)
meta_keywords = Column(String(300), nullable=True)
@@ -195,6 +210,26 @@ class ContentPage(Base):
return "store_default"
return "store_override"
def get_translated_title(self, lang: str, default_lang: str = "fr") -> str:
"""Get title in the given language, falling back to default_lang then self.title."""
if self.title_translations:
return (
self.title_translations.get(lang)
or self.title_translations.get(default_lang)
or self.title
)
return self.title
def get_translated_content(self, lang: str, default_lang: str = "fr") -> str:
"""Get content in the given language, falling back to default_lang then self.content."""
if self.content_translations:
return (
self.content_translations.get(lang)
or self.content_translations.get(default_lang)
or self.content
)
return self.content
def to_dict(self):
"""Convert to dictionary for API responses."""
return {
@@ -206,7 +241,9 @@ class ContentPage(Base):
"store_name": self.store.name if self.store else None,
"slug": self.slug,
"title": self.title,
"title_translations": self.title_translations,
"content": self.content,
"content_translations": self.content_translations,
"content_format": self.content_format,
"template": self.template,
"sections": self.sections,

View File

@@ -85,6 +85,7 @@ class ProductCard(BaseModel):
description: TranslatableText = Field(default_factory=TranslatableText)
url: str = ""
badge: TranslatableText | None = None
link_text: TranslatableText | None = None
class ProductsSection(BaseModel):
@@ -115,6 +116,15 @@ class PricingSection(BaseModel):
use_subscription_tiers: bool = Field(
default=True, description="Pull pricing from subscription_tiers table dynamically"
)
# UI label overrides (CMS-driven, with hardcoded English fallback in template)
monthly_label: TranslatableText | None = None
annual_label: TranslatableText | None = None
save_text: TranslatableText | None = None
popular_badge: TranslatableText | None = None
cta_text: TranslatableText | None = None
per_month_label: TranslatableText | None = None
per_year_label: TranslatableText | None = None
coming_soon_text: TranslatableText | None = None
class CTASection(BaseModel):

View File

@@ -2,13 +2,17 @@
{# Generic template for platform content pages (About, FAQ, Terms, Contact, etc.) #}
{% extends "platform/base.html" %}
{% block title %}{{ page.title }} - Marketplace{% endblock %}
{% set _lang = current_language|default('fr') %}
{% set _page_title = page.get_translated_title(_lang) %}
{% set _page_content = page.get_translated_content(_lang) %}
{% block title %}{{ _page_title }} - Marketplace{% endblock %}
{% block meta_description %}
{% if page.meta_description %}
{{ page.meta_description }}
{% else %}
{{ page.title }} - Multi-Store Marketplace Platform
{{ _page_title }} - Multi-Store Marketplace Platform
{% endif %}
{% endblock %}
@@ -16,7 +20,7 @@
{% if page.meta_keywords %}
{{ page.meta_keywords }}
{% else %}
{{ page.title }}, marketplace, platform
{{ _page_title }}, marketplace, platform
{% endif %}
{% endblock %}
@@ -31,7 +35,7 @@
<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"></path>
</svg>
Home
{{ _("cms.platform.content_page.home") }}
</a>
</li>
<li>
@@ -39,7 +43,7 @@
<svg class="w-4 h-4 text-gray-400 mx-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path>
</svg>
<span class="text-gray-700 dark:text-gray-300 font-medium">{{ page.title }}</span>
<span class="text-gray-700 dark:text-gray-300 font-medium">{{ _page_title }}</span>
</div>
</li>
</ol>
@@ -48,7 +52,7 @@
{# Page Header #}
<div class="mb-12">
<h1 class="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-4">
{{ page.title }}
{{ _page_title }}
</h1>
{# Published date (if available) #}
@@ -57,7 +61,7 @@
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
</svg>
<span>Published {{ page.published_at.strftime('%B %d, %Y') }}</span>
<span>{{ _("cms.platform.content_page.published") }} {{ page.published_at.strftime('%B %d, %Y') }}</span>
</div>
{% endif %}
</div>
@@ -68,11 +72,11 @@
{% if page.content_format == 'markdown' %}
{# Future enhancement: Render with markdown library #}
<div class="markdown-content">
{{ page.content | safe }}{# sanitized: CMS content #}
{{ _page_content | safe }}{# sanitized: CMS content #}
</div>
{% else %}
{# HTML content (default) #}
{{ page.content | safe }}{# sanitized: CMS content #}
{{ _page_content | safe }}{# sanitized: CMS content #}
{% endif %}
</div>
</div>
@@ -81,7 +85,7 @@
{% if page.updated_at %}
<div class="mt-8 pt-6 border-t border-gray-200 dark:border-gray-700 text-center">
<p class="text-sm text-gray-500 dark:text-gray-400">
Last updated: {{ page.updated_at.strftime('%B %d, %Y') }}
{{ _("cms.platform.content_page.last_updated") }} {{ page.updated_at.strftime('%B %d, %Y') }}
</p>
</div>
{% endif %}
@@ -91,23 +95,23 @@
<div class="mt-12 bg-gradient-to-r from-purple-50 to-pink-50 dark:from-purple-900/20 dark:to-pink-900/20 rounded-2xl p-8 text-center">
<h3 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">
{% if page.slug == 'about' %}
Ready to Get Started?
{{ _("cms.platform.content_page.cta_about_title") }}
{% elif page.slug == 'contact' %}
Have Questions?
{{ _("cms.platform.content_page.cta_contact_title") }}
{% endif %}
</h3>
<p class="text-gray-600 dark:text-gray-400 mb-6">
{% if page.slug == 'about' %}
Join thousands of stores already selling on our platform
{{ _("cms.platform.content_page.cta_about_subtitle") }}
{% elif page.slug == 'contact' %}
Our team is here to help you succeed
{{ _("cms.platform.content_page.cta_contact_subtitle") }}
{% endif %}
</p>
<a href="/contact" class="inline-block bg-gray-900 dark:bg-white text-white dark:text-gray-900 px-8 py-3 rounded-lg font-semibold hover:opacity-90 transition">
{% if page.slug == 'about' %}
Contact Sales
{{ _("cms.platform.content_page.cta_about_button") }}
{% elif page.slug == 'contact' %}
Send Us a Message
{{ _("cms.platform.content_page.cta_contact_button") }}
{% endif %}
</a>
</div>

View File

@@ -3,7 +3,7 @@
{% extends "platform/base.html" %}
{% block title %}
{% if page %}{{ page.title }}{% else %}Home{% endif %} - Marketplace
{% if page %}{{ page.title }}{% else %}{{ _("cms.platform.minimal.page_title_fallback") }}{% endif %} - {{ _("cms.platform.minimal.marketplace_suffix") }}
{% endblock %}
{% block content %}
@@ -21,16 +21,16 @@
</div>
{% else %}
<h1 class="text-5xl md:text-7xl font-bold text-gray-900 dark:text-white mb-8 leading-tight">
Multi-Store<br>Marketplace
{{ _("cms.platform.minimal.fallback_title_1") }}<br>{{ _("cms.platform.minimal.fallback_title_2") }}
</h1>
<p class="text-xl text-gray-600 dark:text-gray-400 mb-12 max-w-2xl mx-auto">
The simplest way to launch your online store and connect with customers worldwide.
{{ _("cms.platform.minimal.fallback_subtitle") }}
</p>
{% endif %}
<a href="/contact"
class="inline-block bg-gray-900 dark:bg-white text-white dark:text-gray-900 px-8 py-4 rounded-lg font-semibold hover:opacity-90 transition text-lg">
Get Started
{{ _("cms.platform.minimal.get_started") }}
</a>
</div>
</section>
@@ -44,30 +44,30 @@
<div class="text-center">
<div class="text-4xl mb-4"></div>
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Fast
{{ _("cms.platform.minimal.feat_fast") }}
</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">
Lightning-fast performance optimized for conversions
{{ _("cms.platform.minimal.feat_fast_desc") }}
</p>
</div>
<div class="text-center">
<div class="text-4xl mb-4">🔒</div>
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Secure
{{ _("cms.platform.minimal.feat_secure") }}
</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">
Enterprise-grade security for your peace of mind
{{ _("cms.platform.minimal.feat_secure_desc") }}
</p>
</div>
<div class="text-center">
<div class="text-4xl mb-4">🎨</div>
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
Custom
{{ _("cms.platform.minimal.feat_custom") }}
</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">
Fully customizable to match your brand identity
{{ _("cms.platform.minimal.feat_custom_desc") }}
</p>
</div>
</div>
@@ -80,19 +80,19 @@
<section class="py-24 bg-white dark:bg-gray-800">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl font-bold text-gray-900 dark:text-white mb-6">
Ready to launch?
{{ _("cms.platform.minimal.cta_title") }}
</h2>
<p class="text-gray-600 dark:text-gray-400 mb-8">
Join our marketplace today
{{ _("cms.platform.minimal.cta_subtitle") }}
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/contact"
class="inline-block bg-gray-900 dark:bg-white text-white dark:text-gray-900 px-6 py-3 rounded-lg font-semibold hover:opacity-90 transition">
Contact Us
{{ _("cms.platform.minimal.cta_contact") }}
</a>
<a href="/about"
class="inline-block border-2 border-gray-900 dark:border-white text-gray-900 dark:text-white px-6 py-3 rounded-lg font-semibold hover:bg-gray-50 dark:hover:bg-gray-700 transition">
Learn More
{{ _("cms.platform.minimal.cta_learn_more") }}
</a>
</div>
</div>

View File

@@ -3,7 +3,7 @@
{% extends "platform/base.html" %}
{% block title %}
Orion - The Back-Office for Letzshop Sellers
{{ _("cms.platform.modern.page_title") }}
{% endblock %}
{% block extra_head %}
@@ -43,36 +43,36 @@
{# Left column - Content #}
<div>
<div class="inline-flex items-center px-4 py-2 bg-blue-500/20 backdrop-blur-sm rounded-full text-sm font-medium mb-6 border border-blue-400/30">
<span class="mr-2">🇱🇺</span> Built for Luxembourg E-Commerce
<span class="mr-2">🇱🇺</span> {{ _("cms.platform.modern.hero_title_1") }}
</div>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold mb-6 leading-tight">
The Back-Office<br>
{{ _("cms.platform.modern.hero_title_2").split("Letzshop")[0] }}<br>
<span class="text-transparent bg-clip-text bg-gradient-to-r from-blue-400 to-cyan-400">
Letzshop Doesn't Give You
Letzshop {{ _("cms.platform.modern.hero_title_2").split("Letzshop")[-1] }}
</span>
</h1>
<p class="text-xl md:text-2xl text-gray-300 mb-8 leading-relaxed">
Sync orders, manage inventory, generate invoices with correct VAT, and own your customer data. All in one place.
{{ _("cms.platform.modern.hero_subtitle") }}
</p>
<div class="flex flex-col sm:flex-row gap-4 mb-8">
<a href="/contact"
class="inline-flex items-center justify-center bg-blue-500 hover:bg-blue-600 text-white px-8 py-4 rounded-xl font-bold transition-all duration-200 shadow-lg hover:shadow-xl">
<span>Start 14-Day Free Trial</span>
<span>{{ _("cms.platform.modern.cta_trial", trial_days=trial_days|default(14)) }}</span>
<svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
</svg>
</a>
<a href="#how-it-works"
class="inline-flex items-center justify-center border-2 border-gray-600 text-white px-8 py-4 rounded-xl font-bold hover:bg-white/10 transition-all duration-200">
See How It Works
{{ _("cms.platform.modern.cta_how") }}
</a>
</div>
<p class="text-sm text-gray-400">
No credit card required. Setup in 5 minutes. Cancel anytime.
{{ _("cms.platform.modern.hero_note") }}
</p>
</div>
@@ -85,41 +85,41 @@
<div class="w-3 h-3 rounded-full bg-red-500"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
<div class="w-3 h-3 rounded-full bg-green-500"></div>
<span class="ml-4 text-gray-400 text-sm">Orion Dashboard</span>
<span class="ml-4 text-gray-400 text-sm">{{ _("cms.platform.modern.dashboard_title") }}</span>
</div>
{# Mock dashboard content #}
<div class="p-6 space-y-4">
<div class="grid grid-cols-3 gap-4">
<div class="bg-gray-700/50 rounded-lg p-4">
<div class="text-gray-400 text-xs mb-1">Today's Orders</div>
<div class="text-gray-400 text-xs mb-1">{{ _("cms.platform.modern.todays_orders") }}</div>
<div class="text-2xl font-bold text-white">24</div>
<div class="text-green-400 text-xs">+12% vs yesterday</div>
<div class="text-green-400 text-xs">+12%</div>
</div>
<div class="bg-gray-700/50 rounded-lg p-4">
<div class="text-gray-400 text-xs mb-1">Revenue</div>
<div class="text-gray-400 text-xs mb-1">{{ _("cms.platform.modern.revenue") }}</div>
<div class="text-2xl font-bold text-white">EUR 1,847</div>
<div class="text-green-400 text-xs">+8% vs yesterday</div>
<div class="text-green-400 text-xs">+8%</div>
</div>
<div class="bg-gray-700/50 rounded-lg p-4">
<div class="text-gray-400 text-xs mb-1">Low Stock</div>
<div class="text-gray-400 text-xs mb-1">{{ _("cms.platform.modern.low_stock") }}</div>
<div class="text-2xl font-bold text-yellow-400">3</div>
<div class="text-gray-400 text-xs">items need restock</div>
<div class="text-gray-400 text-xs">{{ _("cms.platform.modern.items_need_restock") }}</div>
</div>
</div>
<div class="bg-gray-700/50 rounded-lg p-4">
<div class="text-gray-400 text-xs mb-3">Recent Orders from Letzshop</div>
<div class="text-gray-400 text-xs mb-3">{{ _("cms.platform.modern.recent_orders") }}</div>
<div class="space-y-2">
<div class="flex justify-between items-center text-sm">
<span class="text-white">#LS-4521</span>
<span class="text-gray-400">Marie D.</span>
<span class="text-green-400">EUR 89.00</span>
<span class="bg-blue-500/20 text-blue-400 px-2 py-0.5 rounded text-xs">Confirmed</span>
<span class="bg-blue-500/20 text-blue-400 px-2 py-0.5 rounded text-xs">{{ _("cms.platform.modern.confirmed") }}</span>
</div>
<div class="flex justify-between items-center text-sm">
<span class="text-white">#LS-4520</span>
<span class="text-gray-400">Jean M.</span>
<span class="text-green-400">EUR 156.50</span>
<span class="bg-purple-500/20 text-purple-400 px-2 py-0.5 rounded text-xs">Shipped</span>
<span class="bg-purple-500/20 text-purple-400 px-2 py-0.5 rounded text-xs">{{ _("cms.platform.modern.shipped") }}</span>
</div>
</div>
</div>
@@ -137,12 +137,12 @@
<section class="py-8 bg-gray-50 dark:bg-gray-800 border-y border-gray-200 dark:border-gray-700">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-col md:flex-row items-center justify-center gap-6 md:gap-12">
<span class="text-gray-500 dark:text-gray-400 font-medium">Official Integration</span>
<span class="text-gray-500 dark:text-gray-400 font-medium">{{ _("cms.platform.modern.badge_integration") }}</span>
<div class="flex items-center gap-3 bg-white dark:bg-gray-700 px-6 py-3 rounded-xl shadow-sm">
<span class="text-2xl">🛒</span>
<span class="font-bold text-gray-900 dark:text-white">Letzshop.lu</span>
</div>
<span class="text-gray-500 dark:text-gray-400 text-sm">Connect in 2 minutes</span>
<span class="text-gray-500 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.badge_connect") }}</span>
</div>
</div>
</section>
@@ -154,36 +154,36 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
Sound Familiar?
{{ _("cms.platform.modern.pain_title") }}
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
These are the daily frustrations of Letzshop sellers
{{ _("cms.platform.modern.pain_subtitle") }}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl p-6">
<div class="text-3xl mb-4">📋</div>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">Manual Order Entry</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">Copy-pasting orders from Letzshop to spreadsheets. Every. Single. Day.</p>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.pain_manual") }}</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.pain_manual_desc") }}</p>
</div>
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl p-6">
<div class="text-3xl mb-4">📦</div>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">Inventory Chaos</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">Stock in Letzshop doesn't match reality. Overselling happens.</p>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.pain_inventory") }}</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.pain_inventory_desc") }}</p>
</div>
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl p-6">
<div class="text-3xl mb-4">🧾</div>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">Wrong VAT Invoices</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">EU customers need correct VAT. Your accountant keeps complaining.</p>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.pain_vat") }}</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.pain_vat_desc") }}</p>
</div>
<div class="bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-xl p-6">
<div class="text-3xl mb-4">👥</div>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">Lost Customers</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">Letzshop owns your customer data. You can't retarget or build loyalty.</p>
<h3 class="font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.pain_customers") }}</h3>
<p class="text-gray-600 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.pain_customers_desc") }}</p>
</div>
</div>
</div>
@@ -196,10 +196,10 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<div class="inline-block px-4 py-2 bg-blue-100 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400 rounded-full text-sm font-semibold mb-4">
How It Works
{{ _("cms.platform.modern.how_title") }}
</div>
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
From Chaos to Control in 4 Steps
{{ _("cms.platform.modern.how_subtitle") }}
</h2>
</div>
@@ -208,8 +208,8 @@
<div class="relative">
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-lg h-full">
<div class="w-12 h-12 rounded-full bg-blue-500 text-white flex items-center justify-center font-bold text-xl mb-6">1</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Connect Letzshop</h3>
<p class="text-gray-600 dark:text-gray-400">Enter your Letzshop API credentials. Done in 2 minutes, no technical skills needed.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.how_step1") }}</h3>
<p class="text-gray-600 dark:text-gray-400">{{ _("cms.platform.modern.how_step1_desc") }}</p>
</div>
<div class="hidden lg:block absolute top-1/2 -right-4 w-8 h-0.5 bg-blue-300"></div>
</div>
@@ -218,8 +218,8 @@
<div class="relative">
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-lg h-full">
<div class="w-12 h-12 rounded-full bg-blue-500 text-white flex items-center justify-center font-bold text-xl mb-6">2</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Orders Flow In</h3>
<p class="text-gray-600 dark:text-gray-400">Orders sync automatically. Confirm and add tracking directly from Orion.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.how_step2") }}</h3>
<p class="text-gray-600 dark:text-gray-400">{{ _("cms.platform.modern.how_step2_desc") }}</p>
</div>
<div class="hidden lg:block absolute top-1/2 -right-4 w-8 h-0.5 bg-blue-300"></div>
</div>
@@ -228,8 +228,8 @@
<div class="relative">
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-lg h-full">
<div class="w-12 h-12 rounded-full bg-blue-500 text-white flex items-center justify-center font-bold text-xl mb-6">3</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Generate Invoices</h3>
<p class="text-gray-600 dark:text-gray-400">One click to create compliant PDF invoices with correct VAT for any EU country.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.how_step3") }}</h3>
<p class="text-gray-600 dark:text-gray-400">{{ _("cms.platform.modern.how_step3_desc") }}</p>
</div>
<div class="hidden lg:block absolute top-1/2 -right-4 w-8 h-0.5 bg-blue-300"></div>
</div>
@@ -238,8 +238,8 @@
<div class="relative">
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-lg h-full">
<div class="w-12 h-12 rounded-full bg-green-500 text-white flex items-center justify-center font-bold text-xl mb-6">4</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Grow Your Business</h3>
<p class="text-gray-600 dark:text-gray-400">Export customers for marketing. Track inventory. Focus on selling, not spreadsheets.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.how_step4") }}</h3>
<p class="text-gray-600 dark:text-gray-400">{{ _("cms.platform.modern.how_step4_desc") }}</p>
</div>
</div>
</div>
@@ -253,13 +253,13 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<div class="inline-block px-4 py-2 bg-green-100 dark:bg-green-900/30 text-green-600 dark:text-green-400 rounded-full text-sm font-semibold mb-4">
Features
{{ _("cms.platform.modern.features_badge") }}
</div>
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
Everything a Letzshop Seller Needs
{{ _("cms.platform.modern.features_title") }}
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
The operational tools Letzshop doesn't provide
{{ _("cms.platform.modern.features_subtitle") }}
</p>
</div>
@@ -271,12 +271,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Automatic Order Sync</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">Orders from Letzshop appear instantly. Confirm orders and sync tracking numbers back automatically.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_order_sync") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_order_sync_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Real-time sync</li>
<li>One-click confirmation</li>
<li>Tracking number sync</li>
<li>{{ _("cms.platform.modern.feat_order_sync_1") }}</li>
<li>{{ _("cms.platform.modern.feat_order_sync_2") }}</li>
<li>{{ _("cms.platform.modern.feat_order_sync_3") }}</li>
</ul>
</div>
@@ -287,12 +287,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Real Inventory Management</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">One source of truth for all stock. Locations, reservations, and incoming stock tracking.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_inventory") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_inventory_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Product locations (bins)</li>
<li>Stock reservations</li>
<li>Low stock alerts</li>
<li>{{ _("cms.platform.modern.feat_inventory_1") }}</li>
<li>{{ _("cms.platform.modern.feat_inventory_2") }}</li>
<li>{{ _("cms.platform.modern.feat_inventory_3") }}</li>
</ul>
</div>
@@ -303,12 +303,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Smart VAT Invoicing</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">Generate PDF invoices with correct VAT rates. Luxembourg, EU countries, B2B reverse charge.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_invoicing") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_invoicing_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Luxembourg 17% VAT</li>
<li>EU destination VAT (OSS)</li>
<li>B2B reverse charge</li>
<li>{{ _("cms.platform.modern.feat_invoicing_1") }}</li>
<li>{{ _("cms.platform.modern.feat_invoicing_2") }}</li>
<li>{{ _("cms.platform.modern.feat_invoicing_3") }}</li>
</ul>
</div>
@@ -319,12 +319,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Own Your Customers</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">All customer data in your database. Export to Mailchimp for marketing campaigns.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_customers") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_customers_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Order history per customer</li>
<li>Lifetime value tracking</li>
<li>CSV export for marketing</li>
<li>{{ _("cms.platform.modern.feat_customers_1") }}</li>
<li>{{ _("cms.platform.modern.feat_customers_2") }}</li>
<li>{{ _("cms.platform.modern.feat_customers_3") }}</li>
</ul>
</div>
@@ -335,12 +335,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Team Management</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">Invite team members with role-based permissions. Everyone works from one dashboard.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_team") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_team_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Multiple users</li>
<li>Role-based access</li>
<li>Activity logging</li>
<li>{{ _("cms.platform.modern.feat_team_1") }}</li>
<li>{{ _("cms.platform.modern.feat_team_2") }}</li>
<li>{{ _("cms.platform.modern.feat_team_3") }}</li>
</ul>
</div>
@@ -351,12 +351,12 @@
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"></path>
</svg>
</div>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">Purchase Orders</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">Track incoming stock from suppliers. Know what's on order and when it arrives.</p>
<h3 class="text-xl font-bold text-gray-900 dark:text-white mb-3">{{ _("cms.platform.modern.feat_purchase_orders") }}</h3>
<p class="text-gray-600 dark:text-gray-400 mb-4">{{ _("cms.platform.modern.feat_purchase_orders_desc") }}</p>
<ul class="text-sm text-gray-500 dark:text-gray-400 space-y-1">
<li>Track supplier orders</li>
<li>Expected arrival dates</li>
<li>Receive and update stock</li>
<li>{{ _("cms.platform.modern.feat_purchase_orders_1") }}</li>
<li>{{ _("cms.platform.modern.feat_purchase_orders_2") }}</li>
<li>{{ _("cms.platform.modern.feat_purchase_orders_3") }}</li>
</ul>
</div>
</div>
@@ -370,175 +370,175 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="text-center mb-16">
<div class="inline-block px-4 py-2 bg-purple-100 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400 rounded-full text-sm font-semibold mb-4">
Pricing
{{ _("cms.platform.modern.pricing_badge") }}
</div>
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
Simple, Transparent Pricing
{{ _("cms.platform.modern.pricing_title") }}
</h2>
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
No per-order fees. No hidden costs. Flat monthly rate.
{{ _("cms.platform.modern.pricing_subtitle") }}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{# Essential #}
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">Essential</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">For solo stores getting started</p>
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.tier_essential") }}</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">{{ _("cms.platform.modern.tier_essential_desc") }}</p>
<div class="mb-6">
<span class="text-4xl font-bold text-gray-900 dark:text-white">EUR 49</span>
<span class="text-gray-500 dark:text-gray-400">/month</span>
<span class="text-4xl font-bold text-gray-900 dark:text-white">{{ _("cms.platform.modern.tier_essential_price") }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ _("cms.platform.modern.pricing_per_month") }}</span>
</div>
<ul class="space-y-3 mb-8 text-sm">
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
100 orders/month
{{ _("cms.platform.modern.tier_essential_feat_1") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
200 products
{{ _("cms.platform.modern.tier_essential_feat_2") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Luxembourg VAT invoices
{{ _("cms.platform.modern.tier_essential_feat_3") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
1 team member
{{ _("cms.platform.modern.tier_essential_feat_4") }}
</li>
</ul>
<a href="/contact" class="block w-full text-center bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white px-6 py-3 rounded-xl font-semibold hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
Start Free Trial
{{ _("cms.platform.modern.tier_essential_cta") }}
</a>
</div>
{# Professional - Highlighted #}
<div class="bg-blue-600 rounded-2xl p-8 shadow-xl relative transform lg:scale-105">
<div class="absolute -top-4 left-1/2 -translate-x-1/2 bg-orange-500 text-white text-xs font-bold px-3 py-1 rounded-full">
MOST POPULAR
{{ _("cms.platform.modern.tier_professional_badge") }}
</div>
<h3 class="text-lg font-bold text-white mb-2">Professional</h3>
<p class="text-blue-200 text-sm mb-4">For growing multi-channel sellers</p>
<h3 class="text-lg font-bold text-white mb-2">{{ _("cms.platform.modern.tier_professional") }}</h3>
<p class="text-blue-200 text-sm mb-4">{{ _("cms.platform.modern.tier_professional_desc") }}</p>
<div class="mb-6">
<span class="text-4xl font-bold text-white">EUR 99</span>
<span class="text-blue-200">/month</span>
<span class="text-4xl font-bold text-white">{{ _("cms.platform.modern.tier_professional_price") }}</span>
<span class="text-blue-200">{{ _("cms.platform.modern.pricing_per_month") }}</span>
</div>
<ul class="space-y-3 mb-8 text-sm">
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
500 orders/month
{{ _("cms.platform.modern.tier_professional_feat_1") }}
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Unlimited products
{{ _("cms.platform.modern.tier_professional_feat_2") }}
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
<strong>EU VAT invoices</strong>
<strong>{{ _("cms.platform.modern.tier_professional_feat_3") }}</strong>
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Product locations
{{ _("cms.platform.modern.tier_professional_feat_4") }}
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Purchase orders
{{ _("cms.platform.modern.tier_professional_feat_5") }}
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Customer export
{{ _("cms.platform.modern.tier_professional_feat_6") }}
</li>
<li class="flex items-center text-blue-100">
<svg class="w-5 h-5 text-green-400 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
3 team members
{{ _("cms.platform.modern.tier_professional_feat_7") }}
</li>
</ul>
<a href="/contact" class="block w-full text-center bg-white text-blue-600 px-6 py-3 rounded-xl font-bold hover:bg-blue-50 transition-colors">
Start Free Trial
{{ _("cms.platform.modern.tier_professional_cta") }}
</a>
</div>
{# Business #}
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">Business</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">For high-volume operations</p>
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.tier_business") }}</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">{{ _("cms.platform.modern.tier_business_desc") }}</p>
<div class="mb-6">
<span class="text-4xl font-bold text-gray-900 dark:text-white">EUR 199</span>
<span class="text-gray-500 dark:text-gray-400">/month</span>
<span class="text-4xl font-bold text-gray-900 dark:text-white">{{ _("cms.platform.modern.tier_business_price") }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ _("cms.platform.modern.pricing_per_month") }}</span>
</div>
<ul class="space-y-3 mb-8 text-sm">
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
2,000 orders/month
{{ _("cms.platform.modern.tier_business_feat_1") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Everything in Professional
{{ _("cms.platform.modern.tier_business_feat_2") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
<strong>Analytics dashboard</strong>
<strong>{{ _("cms.platform.modern.tier_business_feat_3") }}</strong>
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
<strong>API access</strong>
<strong>{{ _("cms.platform.modern.tier_business_feat_4") }}</strong>
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Accounting export
{{ _("cms.platform.modern.tier_business_feat_5") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
10 team members
{{ _("cms.platform.modern.tier_business_feat_6") }}
</li>
</ul>
<a href="/contact" class="block w-full text-center bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white px-6 py-3 rounded-xl font-semibold hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
Start Free Trial
{{ _("cms.platform.modern.tier_business_cta") }}
</a>
</div>
{# Enterprise #}
<div class="bg-white dark:bg-gray-900 rounded-2xl p-8 shadow-sm border border-gray-200 dark:border-gray-700">
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">Enterprise</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">For large operations & agencies</p>
<h3 class="text-lg font-bold text-gray-900 dark:text-white mb-2">{{ _("cms.platform.modern.tier_enterprise") }}</h3>
<p class="text-gray-500 dark:text-gray-400 text-sm mb-4">{{ _("cms.platform.modern.tier_enterprise_desc") }}</p>
<div class="mb-6">
<span class="text-4xl font-bold text-gray-900 dark:text-white">EUR 399+</span>
<span class="text-gray-500 dark:text-gray-400">/month</span>
<span class="text-4xl font-bold text-gray-900 dark:text-white">{{ _("cms.platform.modern.tier_enterprise_price") }}</span>
<span class="text-gray-500 dark:text-gray-400">{{ _("cms.platform.modern.pricing_per_month") }}</span>
</div>
<ul class="space-y-3 mb-8 text-sm">
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Unlimited orders
{{ _("cms.platform.modern.tier_enterprise_feat_1") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Everything in Business
{{ _("cms.platform.modern.tier_enterprise_feat_2") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
<strong>White-label option</strong>
<strong>{{ _("cms.platform.modern.tier_enterprise_feat_3") }}</strong>
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Custom integrations
{{ _("cms.platform.modern.tier_enterprise_feat_4") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
99.9% SLA
{{ _("cms.platform.modern.tier_enterprise_feat_5") }}
</li>
<li class="flex items-center text-gray-600 dark:text-gray-400">
<svg class="w-5 h-5 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
Dedicated support
{{ _("cms.platform.modern.tier_enterprise_feat_6") }}
</li>
</ul>
<a href="/contact" class="block w-full text-center bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white px-6 py-3 rounded-xl font-semibold hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors">
Contact Sales
{{ _("cms.platform.modern.tier_enterprise_cta") }}
</a>
</div>
</div>
<p class="text-center text-gray-500 dark:text-gray-400 mt-8">
All plans include a 14-day free trial. No credit card required.
{{ _("cms.platform.modern.pricing_trial_note") }}
</p>
</div>
</section>
@@ -549,11 +549,11 @@
<section class="py-20 bg-white dark:bg-gray-900">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<div class="inline-block px-4 py-2 bg-yellow-100 dark:bg-yellow-900/30 text-yellow-600 dark:text-yellow-400 rounded-full text-sm font-semibold mb-8">
Built for Luxembourg
{{ _("cms.platform.modern.testimonial_badge") }}
</div>
<blockquote class="text-2xl md:text-3xl font-medium text-gray-900 dark:text-white mb-8 leading-relaxed">
"Finally, a tool that understands what Letzshop sellers actually need. No more spreadsheets, no more VAT headaches."
"{{ _("cms.platform.modern.testimonial_quote") }}"
</blockquote>
<div class="flex items-center justify-center gap-4">
@@ -561,8 +561,8 @@
👩
</div>
<div class="text-left">
<div class="font-semibold text-gray-900 dark:text-white">Marie L.</div>
<div class="text-gray-500 dark:text-gray-400 text-sm">Letzshop Store, Luxembourg City</div>
<div class="font-semibold text-gray-900 dark:text-white">{{ _("cms.platform.modern.testimonial_name") }}</div>
<div class="text-gray-500 dark:text-gray-400 text-sm">{{ _("cms.platform.modern.testimonial_location") }}</div>
</div>
</div>
</div>
@@ -574,16 +574,16 @@
<section class="py-20 bg-gray-900 text-white">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="text-3xl md:text-4xl font-bold mb-6">
Ready to Take Control of Your Letzshop Business?
{{ _("cms.platform.modern.cta_final_title") }}
</h2>
<p class="text-xl text-gray-300 mb-10">
Join Luxembourg stores who've stopped fighting spreadsheets and started growing their business.
{{ _("cms.platform.modern.cta_final_subtitle") }}
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href="/contact"
class="inline-flex items-center justify-center bg-blue-500 hover:bg-blue-600 text-white px-8 py-4 rounded-xl font-bold transition-all duration-200 shadow-lg">
<span>Start Your 14-Day Free Trial</span>
<span>{{ _("cms.platform.modern.cta_final_trial") }}</span>
<svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"></path>
</svg>
@@ -591,7 +591,7 @@
</div>
<p class="mt-8 text-sm text-gray-400">
No credit card required. Setup in 5 minutes. Full Professional features during trial.
{{ _("cms.platform.modern.cta_final_note") }}
</p>
</div>
</section>

View File

@@ -8,23 +8,28 @@
- tiers: List of subscription tiers from DB (passed via context)
#}
{# Helper macro: resolve a TranslatableText field with fallback #}
{% macro _t(field, fallback='') %}
{%- if field and field.translations -%}
{{ field.translations.get(lang) or field.translations.get(default_lang) or fallback }}
{%- else -%}
{{ fallback }}
{%- endif -%}
{% endmacro %}
{% macro render_pricing(pricing, lang, default_lang, tiers) %}
{% if pricing and pricing.enabled %}
<section id="pricing" class="py-16 lg:py-24 bg-gray-50 dark:bg-gray-900">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
{# Section header - tries CMS content first, falls back to locale files #}
{# Section header #}
<div class="text-center mb-12">
{% set title = (pricing.title.translations.get(lang) if pricing.title and pricing.title.translations else none)
or (pricing.title.translations.get(default_lang) if pricing.title and pricing.title.translations else none)
or _('cms.platform.pricing.title') or 'Simple, Transparent Pricing' %}
{% set title = _t(pricing.title, 'Simple, Transparent Pricing') %}
<h2 class="text-3xl md:text-4xl font-bold text-gray-900 dark:text-white mb-4">
{{ title }}
</h2>
{% set subtitle = (pricing.subtitle.translations.get(lang) if pricing.subtitle and pricing.subtitle.translations else none)
or (pricing.subtitle.translations.get(default_lang) if pricing.subtitle and pricing.subtitle.translations else none)
or _('cms.platform.pricing.subtitle') or '' %}
{% if subtitle %}
{% set subtitle = _t(pricing.subtitle) %}
{% if subtitle|trim %}
<p class="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
{{ subtitle }}
</p>
@@ -33,11 +38,19 @@
{# 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') %}
<div x-data="{ annual: false }" class="space-y-8">
{# Billing toggle #}
<div class="flex justify-center items-center space-x-4">
<span :class="annual ? 'text-gray-400' : 'text-gray-900 dark:text-white font-semibold'">
{{ _('cms.platform.pricing.monthly') or 'Monthly' }}
{{ monthly_label }}
</span>
<button @click="annual = !annual"
class="relative w-14 h-7 bg-gray-200 dark:bg-gray-700 rounded-full transition-colors"
@@ -46,8 +59,8 @@
:class="annual && 'translate-x-7'"></span>
</button>
<span :class="!annual ? 'text-gray-400' : 'text-gray-900 dark:text-white font-semibold'">
{{ _('cms.platform.pricing.annual') or 'Annual' }}
<span class="text-green-500 text-sm ml-1">{{ _('cms.platform.pricing.save_months') or 'Save 2 months!' }}</span>
{{ annual_label }}
<span class="text-green-500 text-sm ml-1">{{ save_text }}</span>
</span>
</div>
@@ -58,7 +71,7 @@
{% if tier.is_popular %}
<div class="absolute -top-4 left-1/2 -translate-x-1/2">
<span class="bg-indigo-500 text-white text-sm font-semibold px-4 py-1 rounded-full">
{{ _('cms.platform.pricing.most_popular') or 'Most Popular' }}
{{ popular_badge }}
</span>
</div>
{% endif %}
@@ -77,15 +90,15 @@
<span x-text="annual ? '{{ tier.price_annual or (tier.price_monthly * 10)|int }}' : '{{ tier.price_monthly }}'">{{ tier.price_monthly }}</span>
</span>
<span class="text-gray-500 dark:text-gray-400"
x-text="annual ? '{{ _('cms.platform.pricing.per_year') or '/year' }}' : '{{ _('cms.platform.pricing.per_month') or '/month' }}'">
{{ _('cms.platform.pricing.per_month') or '/month' }}
x-text="annual ? '{{ per_year }}' : '{{ per_month }}'">
{{ per_month }}
</span>
</div>
{# CTA button #}
<a href="/signup?tier={{ tier.code }}"
class="block w-full py-3 px-6 rounded-xl font-semibold transition {% if tier.is_popular %}bg-indigo-600 text-white hover:bg-indigo-700{% else %}bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-600{% endif %}">
{{ _('cms.platform.pricing.start_trial') or 'Start Free Trial' }}
{{ cta_text }}
</a>
</div>
@@ -108,8 +121,9 @@
</div>
{% else %}
{# Placeholder when no tiers available #}
{% set coming_soon = _t(pricing.coming_soon_text, 'Pricing plans coming soon') %}
<div class="text-center text-gray-500 dark:text-gray-400 py-8">
{{ _('cms.platform.pricing.coming_soon') or 'Pricing plans coming soon' }}
{{ coming_soon }}
</div>
{% endif %}
</div>

View File

@@ -72,10 +72,12 @@
{# CTA Link #}
{% if product.url %}
{% set link_label = (product.link_text.translations.get(lang) if product.link_text and product.link_text.translations else none)
or (product.link_text.translations.get(default_lang) if product.link_text and product.link_text.translations else none)
or 'Learn More' %}
<a href="{{ product.url }}"
class="inline-flex items-center text-indigo-600 dark:text-indigo-400 font-semibold hover:text-indigo-800 dark:hover:text-indigo-300 transition-colors group-hover:translate-x-1 transform transition-transform">
{% set link_text = product_title or 'Learn More' %}
Learn More
{{ link_label }}
<svg class="w-4 h-4 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"/>
</svg>

View File

@@ -160,7 +160,7 @@ function storeFinderData() {
this.result = await response.json();
} catch (error) {
console.error('Lookup error:', error);
this.result = { found: false, error: 'Failed to lookup. Please try again.' };
this.result = { found: false, error: '{{ _("cms.platform.find_shop.error_lookup") }}' };
} finally {
this.loading = false;
}

View File

@@ -75,7 +75,7 @@
{% for page in header_pages %}
<a href="/{{ page.slug }}"
class="text-gray-700 dark:text-gray-300 hover:text-indigo-600 dark:hover:text-indigo-400 font-medium transition-colors">
{{ page.title }}
{{ page.get_translated_title(current_language|default('fr')) }}
</a>
{% endfor %}
{% endif %}
@@ -153,7 +153,7 @@
{% for page in header_pages %}
<a href="/{{ page.slug }}"
class="block px-4 py-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg">
{{ page.title }}
{{ page.get_translated_title(current_language|default('fr')) }}
</a>
{% endfor %}
{% endif %}
@@ -195,7 +195,7 @@
<li>
<a href="/{{ page.slug }}"
class="text-gray-600 dark:text-gray-400 hover:text-primary dark:hover:text-primary transition-colors">
{{ page.title }}
{{ page.get_translated_title(current_language|default('fr')) }}
</a>
</li>
{% endfor %}
@@ -208,13 +208,13 @@
<div class="mt-12 pt-8 border-t border-gray-200 dark:border-gray-700">
<div class="flex flex-col md:flex-row justify-between items-center">
<p class="text-gray-600 dark:text-gray-400 text-sm">
&copy; {{ current_year }} {{ platform.name if platform else 'Wizard' }}. All rights reserved.
&copy; {{ current_year }} {{ platform.name if platform else 'Wizard' }}. {{ _("cms.platform.footer.all_rights_reserved") }}
</p>
<div class="flex space-x-6 mt-4 md:mt-0">
{% if legal_pages %}
{% for page in legal_pages %}
<a href="/{{ page.slug }}" class="text-gray-600 dark:text-gray-400 hover:text-primary text-sm transition-colors">
{{ page.title }}
{{ page.get_translated_title(current_language|default('fr')) }}
</a>
{% endfor %}
{% else %}