-
- {t.pricing.comingSoon}
-
Essentiel
@@ -441,9 +438,9 @@ export default function SegmentPageClient({ data, lang }: { data: Segment; lang:
))}
-
+
+ {t.pricing.ctaStartTrial}
+
@@ -540,7 +537,7 @@ export default function SegmentPageClient({ data, lang }: { data: Segment; lang:
check_circle
- {t.pricing.features.ai} — 2 000 {t.pricing.features.reqPerMonth}
+ {t.pricing.features.ai} — ≈ 2 000 {t.pricing.features.questionsPerMonth}
{t.pricing.features.aiNeedMore} → Enterprise
diff --git a/src/app/[lang]/signup/SignupClient.tsx b/src/app/[lang]/signup/SignupClient.tsx
new file mode 100644
index 0000000..83a1c6a
--- /dev/null
+++ b/src/app/[lang]/signup/SignupClient.tsx
@@ -0,0 +1,463 @@
+'use client';
+
+import { useEffect, useRef, useState } from 'react';
+import translations, { Language } from '@/data/translations';
+
+const API_BASE = process.env.NEXT_PUBLIC_MANAGER_SERVICE_URL ?? '';
+
+const COUNTRIES = [
+ { code: 'BE', label: { fr: 'Belgique', en: 'Belgium', nl: 'België', de: 'Belgien' } },
+ { code: 'FR', label: { fr: 'France', en: 'France', nl: 'Frankrijk', de: 'Frankreich' } },
+ { code: 'LU', label: { fr: 'Luxembourg', en: 'Luxembourg', nl: 'Luxemburg', de: 'Luxemburg' } },
+ { code: 'NL', label: { fr: 'Pays-Bas', en: 'Netherlands', nl: 'Nederland', de: 'Niederlande' } },
+ { code: 'DE', label: { fr: 'Allemagne', en: 'Germany', nl: 'Duitsland', de: 'Deutschland' } },
+ { code: 'CH', label: { fr: 'Suisse (hors UE)', en: 'Switzerland (non-EU)', nl: 'Zwitserland (niet-EU)', de: 'Schweiz (nicht EU)' } },
+];
+
+type SlugStatus = 'idle' | 'checking' | 'available' | 'taken' | 'short';
+type VatStatus = { kind: 'idle' | 'checking' | 'zero' | 'std' | 'err' | 'unavailable'; message: string };
+type FormState = 'idle' | 'loading' | 'success' | 'error';
+
+function sanitizeSlug(value: string) {
+ return value
+ .toLowerCase()
+ .replace(/[^a-z0-9-]/g, '-')
+ .replace(/-+/g, '-')
+ .replace(/^-/, '');
+}
+
+export default function SignupClient({ lang }: { lang: Language }) {
+ const t = translations[lang].signup;
+
+ const [orgName, setOrgName] = useState('');
+ const [slug, setSlug] = useState('');
+ const [firstName, setFirstName] = useState('');
+ const [lastName, setLastName] = useState('');
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [address, setAddress] = useState('');
+ const [zip, setZip] = useState('');
+ const [city, setCity] = useState('');
+ const [country, setCountry] = useState('BE');
+ const [vat, setVat] = useState('');
+ const [consent, setConsent] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
+
+ const [slugStatus, setSlugStatus] = useState
('idle');
+ const [vatStatus, setVatStatus] = useState({ kind: 'idle', message: '' });
+ const [formState, setFormState] = useState('idle');
+ const [errorMessage, setErrorMessage] = useState('');
+ const [result, setResult] = useState<{ webUrl: string; managerAppUrl: string; trialEndsAt: string } | null>(null);
+
+ const slugTimer = useRef | null>(null);
+ const vatTimer = useRef | null>(null);
+
+ useEffect(() => {
+ if (slugTimer.current) clearTimeout(slugTimer.current);
+ const clean = sanitizeSlug(slug);
+ if (!clean) {
+ setSlugStatus('idle');
+ return;
+ }
+ if (clean.length < 3) {
+ setSlugStatus('short');
+ return;
+ }
+ setSlugStatus('checking');
+ slugTimer.current = setTimeout(async () => {
+ try {
+ const res = await fetch(`${API_BASE}/api/onboarding/check-slug/${clean}`);
+ const data = await res.json();
+ setSlugStatus(data.available ? 'available' : 'taken');
+ } catch {
+ setSlugStatus('idle');
+ }
+ }, 600);
+ return () => { if (slugTimer.current) clearTimeout(slugTimer.current); };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [slug]);
+
+ useEffect(() => {
+ if (vatTimer.current) clearTimeout(vatTimer.current);
+
+ if (country === 'CH') {
+ setVatStatus({ kind: 'zero', message: t.vatZero });
+ return;
+ }
+ if (!vat.trim()) {
+ setVatStatus({ kind: 'std', message: `${t.vatNoNumber} — ${t.vatNoNumberHint}` });
+ return;
+ }
+
+ setVatStatus({ kind: 'checking', message: t.vatChecking });
+ vatTimer.current = setTimeout(async () => {
+ try {
+ const res = await fetch(
+ `${API_BASE}/api/onboarding/validate-vat?country=${encodeURIComponent(country)}&vatNumber=${encodeURIComponent(vat)}`,
+ { method: 'POST' }
+ );
+ const data = await res.json();
+ if (data.valid === null) {
+ setVatStatus({ kind: 'unavailable', message: t.vatUnavailable });
+ } else if (data.valid === false) {
+ setVatStatus({ kind: 'err', message: t.vatInvalid });
+ } else {
+ setVatStatus({ kind: data.vatRate === 0 ? 'zero' : 'std', message: data.vatRate === 0 ? t.vatZero : t.vatDomestic });
+ }
+ } catch {
+ setVatStatus({ kind: 'unavailable', message: t.vatUnavailable });
+ }
+ }, 500);
+ return () => { if (vatTimer.current) clearTimeout(vatTimer.current); };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [vat, country]);
+
+ const trialEndDateLabel = () => {
+ const d = new Date();
+ d.setDate(d.getDate() + 14);
+ return d.toLocaleDateString(lang === 'fr' ? 'fr-BE' : lang === 'nl' ? 'nl-BE' : lang === 'de' ? 'de-DE' : 'en-GB', {
+ day: 'numeric', month: 'long',
+ });
+ };
+
+ const handleSubmit = async (e: React.FormEvent) => {
+ e.preventDefault();
+ const clean = sanitizeSlug(slug);
+
+ if (!orgName.trim() || !firstName.trim() || !lastName.trim() || !email.trim() || password.length < 8 || !clean || !consent) {
+ return;
+ }
+ if (slugStatus === 'taken') return;
+
+ setFormState('loading');
+ try {
+ const res = await fetch(`${API_BASE}/api/onboarding/register`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ organizationName: orgName.trim(),
+ firstName: firstName.trim(),
+ lastName: lastName.trim(),
+ email: email.trim(),
+ password,
+ slug: clean,
+ billingAddress: [address, zip, city].filter(Boolean).join(', ') || null,
+ billingCountry: country,
+ vatNumber: vat.trim() || null,
+ }),
+ });
+
+ if (res.status === 409) {
+ setSlugStatus('taken');
+ setFormState('idle');
+ return;
+ }
+ if (!res.ok) throw new Error('registration failed');
+
+ const data = await res.json();
+ setResult(data);
+ setFormState('success');
+ } catch {
+ setErrorMessage(t.errorGeneric);
+ setFormState('error');
+ }
+ };
+
+ if (formState === 'success' && result) {
+ return (
+
+
+
+ task_alt
+
+
{t.successTitle}
+
{t.successDesc}
+
+
+
{t.recapUrlLabel}
+
{result.webUrl}
+
+
+
{t.recapTrialLabel}
+
{trialEndDateLabel()}
+
+
+
{t.recapEmailLabel}
+
{email}
+
+
+
+ {t.goToApp}
+
+
+
+ );
+ }
+
+ const missing = !orgName.trim() || !firstName.trim() || !lastName.trim() || !email.trim() || password.length < 8 || !sanitizeSlug(slug) || !consent;
+
+ return (
+
+
+
+ {/* Brand panel — always dark, a deliberate brand block independent of page theme */}
+
+
+
+
+
+
+
+
+ MyInfoMate
+
+
+
+ stars
+ {t.planBadge}
+
+
+
+ {t.heroTitle}
+
+
+
+ 39 €
+ {t.priceSuffix}
+
+
+
+ check_circle
+ {t.trialBadge}
+
+
+
+ {[t.feature1, t.feature2, t.feature3, t.feature4].map((f) => (
+ -
+
+ check
+
+ {f}
+
+ ))}
+
+
+
+
+ info
+ {t.watermarkNote}
+
+
+
+ shield
+ {t.trustHosting}
+
+
+ close
+ {t.trustCancel}
+
+
+ support_agent
+ {t.trustSupport}
+
+
+
+
+
+ {/* Form panel — always light */}
+
+
+
+ );
+}
diff --git a/src/app/[lang]/signup/page.tsx b/src/app/[lang]/signup/page.tsx
new file mode 100644
index 0000000..7209bf4
--- /dev/null
+++ b/src/app/[lang]/signup/page.tsx
@@ -0,0 +1,54 @@
+import type { Metadata } from 'next';
+import { notFound } from 'next/navigation';
+import { LOCALES, LOCALE_HTML_LANG, DEFAULT_LOCALE, isLocale, type Locale } from '@/i18n';
+import SignupClient from './SignupClient';
+
+const META_BY_LOCALE: Record = {
+ fr: {
+ title: 'Créer mon compte — Plan Essentiel | MyInfoMate',
+ description: "Démarrez votre essai gratuit de 14 jours sur MyInfoMate, sans carte bancaire. Votre app visiteur web en quelques minutes.",
+ },
+ en: {
+ title: 'Create my account — Essentiel plan | MyInfoMate',
+ description: 'Start your 14-day free trial on MyInfoMate, no card required. Your web visitor app in minutes.',
+ },
+ nl: {
+ title: 'Mijn account aanmaken — Plan Essentieel | MyInfoMate',
+ description: 'Start uw gratis proefperiode van 14 dagen op MyInfoMate, zonder kredietkaart. Uw webbezoekersapp in enkele minuten.',
+ },
+ de: {
+ title: 'Konto erstellen — Essentiel-Plan | MyInfoMate',
+ description: 'Starten Sie Ihre 14-tägige kostenlose Testphase bei MyInfoMate, ohne Kreditkarte. Ihre Web-Besucher-App in wenigen Minuten.',
+ },
+};
+
+export function generateStaticParams() {
+ return LOCALES.map((lang) => ({ lang }));
+}
+
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ lang: string }>;
+}): Promise {
+ const { lang } = await params;
+ if (!isLocale(lang)) return {};
+ const m = META_BY_LOCALE[lang];
+ const languages = Object.fromEntries(LOCALES.map((l) => [LOCALE_HTML_LANG[l], `/${l}/signup`]));
+ return {
+ title: m.title,
+ description: m.description,
+ robots: { index: false, follow: true },
+ alternates: {
+ canonical: `/${lang}/signup`,
+ languages: { ...languages, 'x-default': `/${DEFAULT_LOCALE}/signup` },
+ },
+ };
+}
+
+export default async function SignupPage({ params }: { params: Promise<{ lang: string }> }) {
+ const { lang } = await params;
+ if (!isLocale(lang)) notFound();
+
+ return ;
+}
diff --git a/src/app/globals.css b/src/app/globals.css
index cbd2795..330b9ee 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -69,6 +69,26 @@
animation: float 6s ease-in-out infinite;
}
+@property --border-angle {
+ syntax: '';
+ inherits: false;
+ initial-value: 0deg;
+}
+
+@keyframes spin-border {
+ to { --border-angle: 360deg; }
+}
+
+@utility animated-card-border {
+ background: conic-gradient(
+ from var(--border-angle),
+ transparent 20%,
+ #0df2df 50%,
+ transparent 80%
+ );
+ animation: spin-border 4s linear infinite;
+}
+
@utility scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
diff --git a/src/data/translations.ts b/src/data/translations.ts
index 3bac405..9393c65 100644
--- a/src/data/translations.ts
+++ b/src/data/translations.ts
@@ -194,6 +194,77 @@ const translations = {
messagePlaceholder: 'Parlez-nous de votre projet...',
submitButton: 'Envoyer ma demande',
},
+ signup: {
+ planBadge: 'Plan Essentiel',
+ heroTitle: 'Votre lieu culturel, en ligne en quelques minutes.',
+ priceSuffix: '/ mois HTVA',
+ trialBadge: "14 jours d'essai gratuit — sans carte bancaire",
+ feature1: 'App visiteur web, ouverte par QR code — aucune installation',
+ feature2: 'Contenus, agenda, plans et sections illimités',
+ feature3: 'Multilingue — vos visiteurs choisissent leur langue',
+ feature4: 'Vos couleurs et votre logo, votre adresse dédiée',
+ watermarkNote: "Pendant l'essai, vos pages visiteur affichent un léger filigrane « Aperçu ». Il disparaît dès l'activation de votre abonnement.",
+ trustHosting: 'Hébergé en Europe',
+ trustCancel: 'Résiliable à tout moment',
+ trustSupport: 'Support en français',
+ formTitle: 'Créer mon compte',
+ alreadyAccount: 'Vous avez déjà un espace ?',
+ loginLink: 'Se connecter',
+ sectionOrg: 'Votre organisation',
+ orgNameLabel: "Nom de l'organisation",
+ orgNamePlaceholder: 'Musée des Beaux-Arts',
+ slugLabel: 'Votre adresse dédiée',
+ slugPrefix: 'app.myinfomate.be/',
+ slugPlaceholder: 'votre-musee',
+ slugHintDefault: "Lettres minuscules, chiffres et tirets — c'est l'URL que vos visiteurs scanneront.",
+ slugHintChecking: 'Vérification de la disponibilité…',
+ slugHintTaken: 'Cette adresse est déjà utilisée — essayez un autre nom.',
+ slugHintAvailable: 'Disponible !',
+ slugHintTooShort: 'Au moins 3 caractères.',
+ sectionContact: 'Vos coordonnées',
+ firstNameLabel: 'Prénom',
+ firstNamePlaceholder: 'Camille',
+ lastNameLabel: 'Nom',
+ lastNamePlaceholder: 'Durand',
+ emailLabel: 'E-mail professionnel',
+ emailPlaceholder: 'camille@votre-musee.be',
+ passwordLabel: 'Mot de passe',
+ passwordPlaceholder: 'Au moins 8 caractères',
+ sectionBilling: 'Facturation',
+ addressLabel: 'Adresse',
+ addressPlaceholder: 'Rue de la Culture 12',
+ zipLabel: 'Code postal',
+ zipPlaceholder: '1000',
+ cityLabel: 'Ville',
+ cityPlaceholder: 'Bruxelles',
+ countryLabel: 'Pays',
+ vatLabel: 'N° de TVA',
+ vatOptional: 'optionnel',
+ vatPlaceholder: 'BE 0123.456.789',
+ vatChecking: 'Vérification du numéro de TVA…',
+ vatUnavailable: 'Service de validation TVA indisponible — TVA belge appliquée, à revalider ultérieurement.',
+ vatNoNumber: 'TVA belge 21% appliquée',
+ vatNoNumberHint: "Ajoutez un n° de TVA valide pour l'exonération intracommunautaire.",
+ vatDomestic: 'TVA belge 21% appliquée',
+ vatZero: 'TVA intracommunautaire — 0%',
+ vatInvalid: 'Numéro de TVA invalide',
+ consentPrefix: "J'accepte les",
+ consentTerms: 'conditions générales',
+ consentAnd: 'et la',
+ consentPrivacy: 'politique de confidentialité',
+ consentSuffix: 'de MyInfoMate.',
+ submitCta: 'Démarrer mon essai gratuit',
+ submitting: 'Création de votre espace…',
+ noCardNote: "Aucun prélèvement pendant l'essai. Nous ne demandons pas de carte.",
+ errorSlugTaken: 'Cette adresse est prise — choisissez-en une autre.',
+ errorGeneric: 'Une erreur est survenue, merci de réessayer.',
+ successTitle: 'Bienvenue à bord !',
+ successDesc: 'Votre espace est prêt. Un e-mail de confirmation vient de partir.',
+ recapUrlLabel: 'Votre adresse visiteur',
+ recapTrialLabel: 'Essai gratuit',
+ recapEmailLabel: 'E-mail de confirmation',
+ goToApp: 'Accéder à mon espace',
+ },
pricing: {
sectionLabel: 'Tarifs',
sectionTitle: 'Un plan pour chaque lieu',
@@ -205,8 +276,8 @@ const translations = {
startingFrom: 'À partir de',
recommended: 'Recommandé',
ctaStart: 'Demander une démo',
+ ctaStartTrial: 'Démarrer mon essai gratuit',
ctaContact: 'Nous contacter',
- comingSoon: 'Bientôt disponible',
enterprisePrice: 'Sur devis',
enterpriseDesc: 'Pour les organisations multi-sites ou aux besoins spécifiques (développements custom, accompagnement, SLA renforcé).',
multiYearLabel: 'Budget pluriannuel ?',
@@ -224,7 +295,7 @@ const translations = {
pushNotif: 'Notifications push',
stats: 'Stats de visite',
ai: 'Assistant IA visiteur',
- reqPerMonth: 'req/mois',
+ questionsPerMonth: 'questions de visiteurs / mois',
statsBasic: '30 jours',
statsAdvanced: 'Illimitées',
webDisplayUrl: 'Affichage web sur URL dédiée',
@@ -455,6 +526,77 @@ const translations = {
messagePlaceholder: 'Tell us about your project...',
submitButton: 'Send my request',
},
+ signup: {
+ planBadge: 'Essentiel plan',
+ heroTitle: 'Your cultural venue, online in minutes.',
+ priceSuffix: '/ month excl. VAT',
+ trialBadge: '14-day free trial — no card required',
+ feature1: 'Web visitor app, opened via QR code — no installation',
+ feature2: 'Unlimited content, agenda, maps and sections',
+ feature3: 'Multilingual — your visitors choose their language',
+ feature4: 'Your colors and logo, your dedicated address',
+ watermarkNote: 'During the trial, your visitor pages show a light "Preview" watermark. It disappears as soon as your subscription is activated.',
+ trustHosting: 'Hosted in Europe',
+ trustCancel: 'Cancel anytime',
+ trustSupport: 'Support in French',
+ formTitle: 'Create my account',
+ alreadyAccount: 'Already have a workspace?',
+ loginLink: 'Log in',
+ sectionOrg: 'Your organization',
+ orgNameLabel: 'Organization name',
+ orgNamePlaceholder: 'Museum of Fine Arts',
+ slugLabel: 'Your dedicated address',
+ slugPrefix: 'app.myinfomate.be/',
+ slugPlaceholder: 'your-museum',
+ slugHintDefault: "Lowercase letters, numbers and dashes — this is the URL your visitors will scan.",
+ slugHintChecking: 'Checking availability…',
+ slugHintTaken: 'This address is already taken — try another name.',
+ slugHintAvailable: 'Available!',
+ slugHintTooShort: 'At least 3 characters.',
+ sectionContact: 'Your contact details',
+ firstNameLabel: 'First name',
+ firstNamePlaceholder: 'Camille',
+ lastNameLabel: 'Last name',
+ lastNamePlaceholder: 'Durand',
+ emailLabel: 'Work email',
+ emailPlaceholder: 'camille@your-museum.com',
+ passwordLabel: 'Password',
+ passwordPlaceholder: 'At least 8 characters',
+ sectionBilling: 'Billing',
+ addressLabel: 'Address',
+ addressPlaceholder: '12 Culture Street',
+ zipLabel: 'Postal code',
+ zipPlaceholder: '1000',
+ cityLabel: 'City',
+ cityPlaceholder: 'Brussels',
+ countryLabel: 'Country',
+ vatLabel: 'VAT number',
+ vatOptional: 'optional',
+ vatPlaceholder: 'BE 0123.456.789',
+ vatChecking: 'Checking VAT number…',
+ vatUnavailable: 'VAT validation service unavailable — Belgian VAT applied, to be re-validated later.',
+ vatNoNumber: '21% Belgian VAT applied',
+ vatNoNumberHint: 'Add a valid VAT number for intra-community exemption.',
+ vatDomestic: '21% Belgian VAT applied',
+ vatZero: 'Intra-community VAT — 0%',
+ vatInvalid: 'Invalid VAT number',
+ consentPrefix: 'I accept the',
+ consentTerms: 'terms of service',
+ consentAnd: 'and the',
+ consentPrivacy: 'privacy policy',
+ consentSuffix: 'of MyInfoMate.',
+ submitCta: 'Start my free trial',
+ submitting: 'Creating your workspace…',
+ noCardNote: 'No charge during the trial. We never ask for a card.',
+ errorSlugTaken: 'This address is taken — choose another one.',
+ errorGeneric: 'Something went wrong, please try again.',
+ successTitle: 'Welcome aboard!',
+ successDesc: 'Your workspace is ready. A confirmation email has just been sent.',
+ recapUrlLabel: 'Your visitor address',
+ recapTrialLabel: 'Free trial',
+ recapEmailLabel: 'Confirmation email',
+ goToApp: 'Go to my workspace',
+ },
pricing: {
sectionLabel: 'Pricing',
sectionTitle: 'A plan for every venue',
@@ -466,8 +608,8 @@ const translations = {
startingFrom: 'Starting from',
recommended: 'Recommended',
ctaStart: 'Request a demo',
+ ctaStartTrial: 'Start my free trial',
ctaContact: 'Contact us',
- comingSoon: 'Coming soon',
enterprisePrice: 'Custom quote',
enterpriseDesc: 'For multi-site organizations or specific needs (custom development, onboarding, enhanced SLA).',
multiYearLabel: 'Multi-year budget?',
@@ -485,7 +627,7 @@ const translations = {
pushNotif: 'Push notifications',
stats: 'Visit statistics',
ai: 'AI visitor assistant',
- reqPerMonth: 'req/month',
+ questionsPerMonth: 'visitor questions / month',
statsBasic: '30 days',
statsAdvanced: 'Unlimited',
webDisplayUrl: 'Web display on dedicated URL',
@@ -716,6 +858,77 @@ const translations = {
messagePlaceholder: 'Vertel ons over uw project...',
submitButton: 'Mijn aanvraag verzenden',
},
+ signup: {
+ planBadge: 'Plan Essentieel',
+ heroTitle: 'Uw culturele locatie, online in enkele minuten.',
+ priceSuffix: '/ maand excl. BTW',
+ trialBadge: '14 dagen gratis proberen — geen kredietkaart nodig',
+ feature1: 'Web-bezoekersapp, geopend via QR-code — geen installatie',
+ feature2: 'Onbeperkte inhoud, agenda, plannen en secties',
+ feature3: 'Meertalig — uw bezoekers kiezen hun taal',
+ feature4: 'Uw kleuren en logo, uw eigen adres',
+ watermarkNote: 'Tijdens de proefperiode tonen uw bezoekerspagina\'s een licht "Preview"-watermerk. Dit verdwijnt zodra uw abonnement actief is.',
+ trustHosting: 'Gehost in Europa',
+ trustCancel: 'Op elk moment opzegbaar',
+ trustSupport: 'Ondersteuning in het Frans',
+ formTitle: 'Mijn account aanmaken',
+ alreadyAccount: 'Heeft u al een omgeving?',
+ loginLink: 'Inloggen',
+ sectionOrg: 'Uw organisatie',
+ orgNameLabel: 'Naam van de organisatie',
+ orgNamePlaceholder: 'Museum voor Schone Kunsten',
+ slugLabel: 'Uw eigen adres',
+ slugPrefix: 'app.myinfomate.be/',
+ slugPlaceholder: 'uw-museum',
+ slugHintDefault: 'Kleine letters, cijfers en streepjes — dit is de URL die uw bezoekers zullen scannen.',
+ slugHintChecking: 'Beschikbaarheid controleren…',
+ slugHintTaken: 'Dit adres is al in gebruik — probeer een andere naam.',
+ slugHintAvailable: 'Beschikbaar!',
+ slugHintTooShort: 'Minstens 3 tekens.',
+ sectionContact: 'Uw gegevens',
+ firstNameLabel: 'Voornaam',
+ firstNamePlaceholder: 'Camille',
+ lastNameLabel: 'Naam',
+ lastNamePlaceholder: 'Durand',
+ emailLabel: 'Professioneel e-mailadres',
+ emailPlaceholder: 'camille@uw-museum.be',
+ passwordLabel: 'Wachtwoord',
+ passwordPlaceholder: 'Minstens 8 tekens',
+ sectionBilling: 'Facturatie',
+ addressLabel: 'Adres',
+ addressPlaceholder: 'Cultuurstraat 12',
+ zipLabel: 'Postcode',
+ zipPlaceholder: '1000',
+ cityLabel: 'Stad',
+ cityPlaceholder: 'Brussel',
+ countryLabel: 'Land',
+ vatLabel: 'BTW-nummer',
+ vatOptional: 'optioneel',
+ vatPlaceholder: 'BE 0123.456.789',
+ vatChecking: 'BTW-nummer controleren…',
+ vatUnavailable: 'BTW-validatiedienst niet beschikbaar — Belgische BTW toegepast, later opnieuw te valideren.',
+ vatNoNumber: '21% Belgische BTW toegepast',
+ vatNoNumberHint: 'Voeg een geldig BTW-nummer toe voor intracommunautaire vrijstelling.',
+ vatDomestic: '21% Belgische BTW toegepast',
+ vatZero: 'Intracommunautaire BTW — 0%',
+ vatInvalid: 'Ongeldig BTW-nummer',
+ consentPrefix: 'Ik aanvaard de',
+ consentTerms: 'algemene voorwaarden',
+ consentAnd: 'en het',
+ consentPrivacy: 'privacybeleid',
+ consentSuffix: 'van MyInfoMate.',
+ submitCta: 'Start mijn gratis proefperiode',
+ submitting: 'Uw omgeving wordt aangemaakt…',
+ noCardNote: 'Geen afschrijving tijdens de proefperiode. Wij vragen nooit om een kaart.',
+ errorSlugTaken: 'Dit adres is al bezet — kies een andere.',
+ errorGeneric: 'Er is iets misgegaan, probeer het opnieuw.',
+ successTitle: 'Welkom aan boord!',
+ successDesc: 'Uw omgeving is klaar. Er is zojuist een bevestigingsmail verstuurd.',
+ recapUrlLabel: 'Uw bezoekersadres',
+ recapTrialLabel: 'Gratis proefperiode',
+ recapEmailLabel: 'Bevestigingsmail',
+ goToApp: 'Naar mijn omgeving',
+ },
pricing: {
sectionLabel: 'Tarieven',
sectionTitle: 'Een plan voor elke locatie',
@@ -727,8 +940,8 @@ const translations = {
startingFrom: 'Vanaf',
recommended: 'Aanbevolen',
ctaStart: 'Demo aanvragen',
+ ctaStartTrial: 'Start mijn gratis proefperiode',
ctaContact: 'Neem contact op',
- comingSoon: 'Binnenkort beschikbaar',
enterprisePrice: 'Op maat',
enterpriseDesc: 'Voor organisaties met meerdere locaties of specifieke behoeften (maatwerk ontwikkeling, begeleiding, verbeterde SLA).',
multiYearLabel: 'Meerjarig budget?',
@@ -746,7 +959,7 @@ const translations = {
pushNotif: 'Pushmeldingen',
stats: 'Bezoekstatistieken',
ai: 'AI-bezoekersassistent',
- reqPerMonth: 'req/maand',
+ questionsPerMonth: 'bezoekersvragen / maand',
statsBasic: '30 dagen',
statsAdvanced: 'Onbeperkt',
webDisplayUrl: 'Webweergave op toegewijd URL',
@@ -977,6 +1190,77 @@ const translations = {
messagePlaceholder: 'Erzählen Sie uns von Ihrem Projekt...',
submitButton: 'Meine Anfrage senden',
},
+ signup: {
+ planBadge: 'Essentiel-Plan',
+ heroTitle: 'Ihr Kulturort, online in wenigen Minuten.',
+ priceSuffix: '/ Monat zzgl. MwSt.',
+ trialBadge: '14 Tage kostenlos testen — keine Kreditkarte nötig',
+ feature1: 'Web-Besucher-App, per QR-Code geöffnet — keine Installation',
+ feature2: 'Unbegrenzte Inhalte, Agenda, Pläne und Sektionen',
+ feature3: 'Mehrsprachig — Ihre Besucher wählen ihre Sprache',
+ feature4: 'Ihre Farben und Ihr Logo, Ihre eigene Adresse',
+ watermarkNote: 'Während der Testphase zeigen Ihre Besucherseiten ein leichtes "Vorschau"-Wasserzeichen. Es verschwindet, sobald Ihr Abonnement aktiviert ist.',
+ trustHosting: 'Gehostet in Europa',
+ trustCancel: 'Jederzeit kündbar',
+ trustSupport: 'Support auf Französisch',
+ formTitle: 'Konto erstellen',
+ alreadyAccount: 'Haben Sie bereits einen Arbeitsbereich?',
+ loginLink: 'Anmelden',
+ sectionOrg: 'Ihre Organisation',
+ orgNameLabel: 'Name der Organisation',
+ orgNamePlaceholder: 'Museum der Schönen Künste',
+ slugLabel: 'Ihre eigene Adresse',
+ slugPrefix: 'app.myinfomate.be/',
+ slugPlaceholder: 'ihr-museum',
+ slugHintDefault: 'Kleinbuchstaben, Zahlen und Bindestriche — dies ist die URL, die Ihre Besucher scannen werden.',
+ slugHintChecking: 'Verfügbarkeit wird geprüft…',
+ slugHintTaken: 'Diese Adresse ist bereits vergeben — wählen Sie einen anderen Namen.',
+ slugHintAvailable: 'Verfügbar!',
+ slugHintTooShort: 'Mindestens 3 Zeichen.',
+ sectionContact: 'Ihre Kontaktdaten',
+ firstNameLabel: 'Vorname',
+ firstNamePlaceholder: 'Camille',
+ lastNameLabel: 'Nachname',
+ lastNamePlaceholder: 'Durand',
+ emailLabel: 'Geschäftliche E-Mail',
+ emailPlaceholder: 'camille@ihr-museum.de',
+ passwordLabel: 'Passwort',
+ passwordPlaceholder: 'Mindestens 8 Zeichen',
+ sectionBilling: 'Rechnungsstellung',
+ addressLabel: 'Adresse',
+ addressPlaceholder: 'Kulturstraße 12',
+ zipLabel: 'Postleitzahl',
+ zipPlaceholder: '1000',
+ cityLabel: 'Stadt',
+ cityPlaceholder: 'Brüssel',
+ countryLabel: 'Land',
+ vatLabel: 'USt-IdNr.',
+ vatOptional: 'optional',
+ vatPlaceholder: 'BE 0123.456.789',
+ vatChecking: 'USt-IdNr. wird geprüft…',
+ vatUnavailable: 'USt-Validierungsdienst nicht verfügbar — belgische MwSt. angewendet, später erneut zu validieren.',
+ vatNoNumber: '21% belgische MwSt. angewendet',
+ vatNoNumberHint: 'Fügen Sie eine gültige USt-IdNr. für die innergemeinschaftliche Befreiung hinzu.',
+ vatDomestic: '21% belgische MwSt. angewendet',
+ vatZero: 'Innergemeinschaftliche MwSt. — 0%',
+ vatInvalid: 'Ungültige USt-IdNr.',
+ consentPrefix: 'Ich akzeptiere die',
+ consentTerms: 'Allgemeinen Geschäftsbedingungen',
+ consentAnd: 'und die',
+ consentPrivacy: 'Datenschutzrichtlinie',
+ consentSuffix: 'von MyInfoMate.',
+ submitCta: 'Kostenlos testen',
+ submitting: 'Ihr Arbeitsbereich wird erstellt…',
+ noCardNote: 'Keine Abbuchung während der Testphase. Wir fragen nie nach einer Karte.',
+ errorSlugTaken: 'Diese Adresse ist vergeben — wählen Sie eine andere.',
+ errorGeneric: 'Etwas ist schiefgelaufen, bitte versuchen Sie es erneut.',
+ successTitle: 'Willkommen an Bord!',
+ successDesc: 'Ihr Arbeitsbereich ist bereit. Eine Bestätigungs-E-Mail wurde soeben versendet.',
+ recapUrlLabel: 'Ihre Besucheradresse',
+ recapTrialLabel: 'Kostenlose Testphase',
+ recapEmailLabel: 'Bestätigungs-E-Mail',
+ goToApp: 'Zu meinem Arbeitsbereich',
+ },
pricing: {
sectionLabel: 'Preise',
sectionTitle: 'Ein Plan für jeden Standort',
@@ -988,8 +1272,8 @@ const translations = {
startingFrom: 'Ab',
recommended: 'Empfohlen',
ctaStart: 'Demo anfordern',
+ ctaStartTrial: 'Kostenlos testen',
ctaContact: 'Kontaktieren Sie uns',
- comingSoon: 'Demnächst verfügbar',
enterprisePrice: 'Auf Anfrage',
enterpriseDesc: 'Für Organisationen mit mehreren Standorten oder spezifischen Anforderungen (individuelle Entwicklung, Begleitung, erweiterter SLA).',
multiYearLabel: 'Mehrjähriges Budget?',
@@ -1007,7 +1291,7 @@ const translations = {
pushNotif: 'Push-Benachrichtigungen',
stats: 'Besucherstatistiken',
ai: 'KI-Besucherassistent',
- reqPerMonth: 'Req/Monat',
+ questionsPerMonth: 'Besucherfragen / Monat',
statsBasic: '30 Tage',
statsAdvanced: 'Unbegrenzt',
webDisplayUrl: 'Web-Anzeige auf dedizierter URL',