diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts index 4e80bcd..484d579 100644 --- a/frontend/src/app/app.routes.ts +++ b/frontend/src/app/app.routes.ts @@ -1,50 +1,61 @@ import { Routes } from '@angular/router'; +const appChildRoutes: Routes = [ + { + path: '', + loadComponent: () => import('./features/home/home.component').then(m => m.HomeComponent) + }, + { + path: 'calculator', + loadChildren: () => import('./features/calculator/calculator.routes').then(m => m.CALCULATOR_ROUTES) + }, + { + path: 'shop', + loadChildren: () => import('./features/shop/shop.routes').then(m => m.SHOP_ROUTES) + }, + { + path: 'about', + loadChildren: () => import('./features/about/about.routes').then(m => m.ABOUT_ROUTES) + }, + { + path: 'contact', + loadChildren: () => import('./features/contact/contact.routes').then(m => m.CONTACT_ROUTES) + }, + { + path: 'checkout', + loadComponent: () => import('./features/checkout/checkout.component').then(m => m.CheckoutComponent) + }, + { + path: 'order/:orderId', + loadComponent: () => import('./features/order/order.component').then(m => m.OrderComponent) + }, + { + path: 'co/:orderId', + loadComponent: () => import('./features/order/order.component').then(m => m.OrderComponent) + }, + { + path: '', + loadChildren: () => import('./features/legal/legal.routes').then(m => m.LEGAL_ROUTES) + }, + { + path: '**', + redirectTo: '' + } +]; + export const routes: Routes = [ + { + path: ':lang', + loadComponent: () => import('./core/layout/layout.component').then(m => m.LayoutComponent), + children: appChildRoutes + }, { path: '', loadComponent: () => import('./core/layout/layout.component').then(m => m.LayoutComponent), - children: [ - { - path: '', - loadComponent: () => import('./features/home/home.component').then(m => m.HomeComponent) - }, - { - path: 'calculator', - loadChildren: () => import('./features/calculator/calculator.routes').then(m => m.CALCULATOR_ROUTES) - }, - { - path: 'shop', - loadChildren: () => import('./features/shop/shop.routes').then(m => m.SHOP_ROUTES) - }, - { - path: 'about', - loadChildren: () => import('./features/about/about.routes').then(m => m.ABOUT_ROUTES) - }, - { - path: 'contact', - loadChildren: () => import('./features/contact/contact.routes').then(m => m.CONTACT_ROUTES) - }, - { - path: 'checkout', - loadComponent: () => import('./features/checkout/checkout.component').then(m => m.CheckoutComponent) - }, - { - path: 'order/:orderId', - loadComponent: () => import('./features/order/order.component').then(m => m.OrderComponent) - }, - { - path: 'co/:orderId', - loadComponent: () => import('./features/order/order.component').then(m => m.OrderComponent) - }, - { - path: '', - loadChildren: () => import('./features/legal/legal.routes').then(m => m.LEGAL_ROUTES) - }, - { - path: '**', - redirectTo: '' - } - ] + children: appChildRoutes + }, + { + path: '**', + redirectTo: '' } ]; diff --git a/frontend/src/app/core/layout/navbar.component.html b/frontend/src/app/core/layout/navbar.component.html index 189ff6f..15347c0 100644 --- a/frontend/src/app/core/layout/navbar.component.html +++ b/frontend/src/app/core/layout/navbar.component.html @@ -17,9 +17,15 @@
- +
diff --git a/frontend/src/app/core/layout/navbar.component.scss b/frontend/src/app/core/layout/navbar.component.scss index f132074..6b0da84 100644 --- a/frontend/src/app/core/layout/navbar.component.scss +++ b/frontend/src/app/core/layout/navbar.component.scss @@ -44,15 +44,29 @@ } .lang-switch { - background: none; + background-color: var(--color-bg-card); border: 1px solid var(--color-border); border-radius: var(--radius-sm); - padding: 2px 6px; + padding: 2px 22px 2px 8px; cursor: pointer; font-size: 0.875rem; font-weight: 600; color: var(--color-text-muted); + appearance: none; + background-image: + linear-gradient(45deg, transparent 50%, currentColor 50%), + linear-gradient(135deg, currentColor 50%, transparent 50%); + background-position: + calc(100% - 10px) calc(50% - 2px), + calc(100% - 5px) calc(50% - 2px); + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; + &:hover { color: var(--color-text); border-color: var(--color-text); } + &:focus-visible { + outline: 2px solid var(--color-brand); + outline-offset: 1px; + } } .icon-placeholder { diff --git a/frontend/src/app/core/layout/navbar.component.ts b/frontend/src/app/core/layout/navbar.component.ts index a2e548f..0cfe61a 100644 --- a/frontend/src/app/core/layout/navbar.component.ts +++ b/frontend/src/app/core/layout/navbar.component.ts @@ -2,7 +2,6 @@ import { Component } from '@angular/core'; import { RouterLink, RouterLinkActive } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { LanguageService } from '../services/language.service'; -import { AppButtonComponent } from '../../shared/components/app-button/app-button.component'; @Component({ selector: 'app-navbar', @@ -13,12 +12,19 @@ import { AppButtonComponent } from '../../shared/components/app-button/app-butto }) export class NavbarComponent { isMenuOpen = false; + readonly languageOptions: Array<{ value: 'it' | 'en' | 'de' | 'fr'; label: string }> = [ + { value: 'it', label: 'IT' }, + { value: 'en', label: 'EN' }, + { value: 'de', label: 'DE' }, + { value: 'fr', label: 'FR' } + ]; constructor(public langService: LanguageService) {} - toggleLang() { - const newLang = this.langService.currentLang() === 'it' ? 'en' : 'it'; - this.langService.switchLang(newLang); + onLanguageChange(event: Event): void { + const select = event.target as HTMLSelectElement; + const lang = select.value as 'it' | 'en' | 'de' | 'fr'; + this.langService.switchLang(lang); } toggleMenu() { diff --git a/frontend/src/app/core/services/language.service.ts b/frontend/src/app/core/services/language.service.ts index ead4dc0..742101e 100644 --- a/frontend/src/app/core/services/language.service.ts +++ b/frontend/src/app/core/services/language.service.ts @@ -1,20 +1,126 @@ import { Injectable, signal } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; +import { NavigationEnd, PRIMARY_OUTLET, Router, UrlTree } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class LanguageService { - currentLang = signal('it'); + currentLang = signal<'it' | 'en' | 'de' | 'fr'>('it'); + private readonly supportedLangs: Array<'it' | 'en' | 'de' | 'fr'> = ['it', 'en', 'de', 'fr']; - constructor(private translate: TranslateService) { - this.translate.addLangs(['it', 'en']); + constructor( + private translate: TranslateService, + private router: Router + ) { + this.translate.addLangs(this.supportedLangs); this.translate.setDefaultLang('it'); - this.translate.use('it'); + + const initialTree = this.router.parseUrl(this.router.url); + const initialSegments = this.getPrimarySegments(initialTree); + const queryLang = this.getQueryLang(initialTree); + const initialLang = this.isSupportedLang(initialSegments[0]) + ? initialSegments[0] + : (this.isSupportedLang(queryLang) ? queryLang : 'it'); + this.applyLanguage(initialLang); + this.ensureLanguageInPath(initialTree); + + this.router.events.subscribe(event => { + if (!(event instanceof NavigationEnd)) { + return; + } + + this.ensureLanguageInPath(this.router.parseUrl(this.router.url)); + }); } - switchLang(lang: string) { + switchLang(lang: 'it' | 'en' | 'de' | 'fr') { + if (!this.isSupportedLang(lang)) { + return; + } + this.applyLanguage(lang); + + const currentTree = this.router.parseUrl(this.router.url); + const segments = this.getPrimarySegments(currentTree); + + let targetSegments: string[]; + if (segments.length === 0) { + targetSegments = [lang]; + } else if (this.isSupportedLang(segments[0]) || this.looksLikeLangToken(segments[0])) { + targetSegments = [lang, ...segments.slice(1)]; + } else { + targetSegments = [lang, ...segments]; + } + + this.navigateIfChanged(currentTree, targetSegments); + } + + private ensureLanguageInPath(urlTree: UrlTree): void { + const segments = this.getPrimarySegments(urlTree); + + if (segments.length > 0 && this.isSupportedLang(segments[0])) { + this.applyLanguage(segments[0]); + return; + } + + const queryLang = this.getQueryLang(urlTree); + const activeLang = this.isSupportedLang(queryLang) ? queryLang : this.currentLang(); + if (activeLang !== this.currentLang()) { + this.applyLanguage(activeLang); + } + let targetSegments: string[]; + + if (segments.length === 0) { + targetSegments = [activeLang]; + } else if (this.looksLikeLangToken(segments[0])) { + targetSegments = [activeLang, ...segments.slice(1)]; + } else { + targetSegments = [activeLang, ...segments]; + } + + this.navigateIfChanged(urlTree, targetSegments); + } + + private getPrimarySegments(urlTree: UrlTree): string[] { + const primaryGroup = urlTree.root.children[PRIMARY_OUTLET]; + if (!primaryGroup) { + return []; + } + return primaryGroup.segments.map(segment => segment.path.toLowerCase()); + } + + private getQueryLang(urlTree: UrlTree): string | null { + const lang = urlTree.queryParams['lang']; + return typeof lang === 'string' ? lang.toLowerCase() : null; + } + + private isSupportedLang(lang: string | null | undefined): lang is 'it' | 'en' | 'de' | 'fr' { + return typeof lang === 'string' && this.supportedLangs.includes(lang as 'it' | 'en' | 'de' | 'fr'); + } + + private looksLikeLangToken(segment: string | null | undefined): boolean { + return typeof segment === 'string' && /^[a-z]{2}(?:-[a-z]{2})?$/i.test(segment); + } + + private applyLanguage(lang: 'it' | 'en' | 'de' | 'fr'): void { + if (this.currentLang() === lang && this.translate.currentLang === lang) { + return; + } this.translate.use(lang); this.currentLang.set(lang); } + + private navigateIfChanged(currentTree: UrlTree, targetSegments: string[]): void { + const { lang: _unusedLang, ...queryParams } = currentTree.queryParams; + const targetTree = this.router.createUrlTree(['/', ...targetSegments], { + queryParams, + fragment: currentTree.fragment ?? undefined + }); + + if (this.router.serializeUrl(targetTree) === this.router.serializeUrl(currentTree)) { + return; + } + + this.router.navigateByUrl(targetTree, { replaceUrl: true }); + } } diff --git a/frontend/src/assets/i18n/de.json b/frontend/src/assets/i18n/de.json new file mode 100644 index 0000000..b1af8bc --- /dev/null +++ b/frontend/src/assets/i18n/de.json @@ -0,0 +1,546 @@ +{ + "NAV": { + "HOME": "Startseite", + "CALCULATOR": "Rechner", + "SHOP": "Shop", + "ABOUT": "Über uns", + "CONTACT": "Kontakt", + "LANGUAGE_SELECTOR": "Sprachauswahl" + }, + "QUOTE": { + "CONSULT": "Beratung anfragen", + "PROCEED_ORDER": "Zur Bestellung", + "TOTAL": "Gesamt", + "MAX_QTY_NOTICE": "Für Mengen über {{max}} Stück bitte Beratung anfragen." + }, + "USER_DETAILS": { + "TITLE": "Ihre Daten", + "SUMMARY_TITLE": "Zusammenfassung", + "NAME": "Vorname", + "NAME_PLACEHOLDER": "Ihr Vorname", + "SURNAME": "Nachname", + "SURNAME_PLACEHOLDER": "Ihr Nachname", + "EMAIL": "E-Mail", + "EMAIL_PLACEHOLDER": "ihre@email.com", + "PHONE": "Telefon", + "PHONE_PLACEHOLDER": "+41 ...", + "ADDRESS": "Adresse", + "ADDRESS_PLACEHOLDER": "Straße und Nummer", + "ZIP": "PLZ", + "ZIP_PLACEHOLDER": "0000", + "CITY": "Ort", + "CITY_PLACEHOLDER": "Ort", + "SUBMIT": "Weiter", + "DEFAULT_COLOR": "Standard" + }, + "FOOTER": { + "PRIVACY": "Datenschutz", + "TERMS": "AGB", + "CONTACT": "Kontakt" + }, + "CALC": { + "TITLE": "3D-Angebot berechnen", + "SUBTITLE": "Laden Sie Ihre 3D-Datei (STL, 3MF, STEP) hoch, stellen Sie Qualität und Farbe ein und berechnen Sie sofort Preis und Lieferzeit.", + "CTA_START": "Jetzt starten", + "BUSINESS": "Unternehmen", + "PRIVATE": "Privat", + "MODE_EASY": "Basis", + "MODE_ADVANCED": "Erweitert", + "UPLOAD_LABEL": "Ziehen Sie Ihre 3D-Datei hierher", + "UPLOAD_SUB": "Wir unterstützen STL, 3MF, STEP bis 50MB", + "MATERIAL": "Material", + "QUALITY": "Qualität", + "QUANTITY": "Menge", + "NOTES": "Zusätzliche Hinweise", + "NOZZLE": "Düsendurchmesser", + "INFILL": "Fülldichte (%)", + "PATTERN": "Füllmuster", + "LAYER_HEIGHT": "Schichthöhe", + "SUPPORT": "Stützstrukturen", + "SUPPORT_DESC": "Stützen für Überhänge aktivieren", + "CALCULATE": "Angebot berechnen", + "RESULT": "Geschätztes Angebot", + "TIME": "Druckzeit", + "MACHINE_COST": "Maschinenkosten", + "COST": "Gesamtkosten", + "ORDER": "Jetzt bestellen", + "CONSULT": "Beratung anfragen", + "ERROR_GENERIC": "Bei der Angebotsberechnung ist ein Fehler aufgetreten.", + "NEW_QUOTE": "Neues Angebot berechnen", + "ORDER_SUCCESS_TITLE": "Bestellung erfolgreich gesendet", + "ORDER_SUCCESS_DESC": "Wir haben die Details Ihrer Bestellung erhalten. Sie erhalten in Kürze eine Bestätigungs-E-Mail mit Zahlungsinformationen.", + "BENEFITS_TITLE": "Warum uns wählen?", + "BENEFITS_1": "Automatisches Angebot mit sofortigen Kosten und Zeiten", + "BENEFITS_2": "Ausgewählte Materialien und Qualitätskontrolle", + "BENEFITS_3": "CAD-Beratung, falls die Datei Änderungen benötigt", + "ERR_FILE_REQUIRED": "Die Datei ist erforderlich.", + "STEP_WARNING": "Die 3D-Ansicht ist mit STEP- und 3MF-Dateien nicht kompatibel", + "REMOVE_FILE": "Datei entfernen", + "FALLBACK_MATERIAL": "PLA (Fallback)", + "FALLBACK_QUALITY_STANDARD": "Standard", + "ERR_FILE_TOO_LARGE": "Einige Dateien überschreiten das 200MB-Limit und wurden nicht hinzugefügt.", + "PRINT_SPEED": "Druckgeschwindigkeit", + "COLOR": "Farbe", + "ANALYZING_TITLE": "Analyse läuft...", + "ANALYZING_TEXT": "Wir analysieren die Geometrie und berechnen den Werkzeugpfad.", + "QTY_SHORT": "MENGE", + "COLOR_LABEL": "FARBE", + "ADD_FILES": "Dateien hinzufügen", + "UPLOADING": "Hochladen...", + "PROCESSING": "Verarbeitung...", + "NOTES_PLACEHOLDER": "Spezifische Anweisungen...", + "SETUP_NOTE": "* Beinhaltet {{cost}} als Einrichtungskosten", + "SHIPPING_NOTE": "** Versandkosten ausgeschlossen, werden im nächsten Schritt berechnet" + }, + "SHOP": { + "TITLE": "Technische Lösungen", + "SUBTITLE": "Fertige Produkte, die praktische Probleme lösen", + "WIP_EYEBROW": "Work in progress", + "WIP_TITLE": "Shop im Aufbau", + "WIP_SUBTITLE": "Wir bereiten einen Shop mit ausgewählten Produkten und Funktionen zur automatischen Erstellung vor!", + "WIP_CTA_CALC": "Zum Rechner", + "WIP_RETURN_LATER": "Kommen Sie später wieder", + "WIP_NOTE": "Wir legen Wert darauf, die Dinge richtig zu machen: In der Zwischenzeit können Sie Preis und Lieferzeit einer 3D-Datei sofort mit unserem Rechner berechnen.", + "ADD_CART": "In den Warenkorb", + "BACK": "Zurück zum Shop", + "NOT_FOUND": "Produkt nicht gefunden.", + "DETAILS": "Details", + "MOCK_ADD_CART": "Zum Warenkorb hinzugefügt (Mock)", + "SUCCESS_TITLE": "Zum Warenkorb hinzugefügt", + "SUCCESS_DESC": "Das Produkt wurde erfolgreich zum Warenkorb hinzugefügt.", + "CONTINUE": "Weiter", + "CATEGORIES": { + "FILAMENTS": "Filamente", + "ACCESSORIES": "Zubehör" + }, + "PRODUCTS": { + "P1": { + "NAME": "PLA-Standardfilament", + "DESC": "Der Klassiker für jeden Druck, einfach und zuverlässig." + }, + "P2": { + "NAME": "PETG Tough Filament", + "DESC": "Stoß- und temperaturbeständig." + }, + "P3": { + "NAME": "Düsenset (0.4mm)", + "DESC": "Ersatzset für FDM-Extruder." + } + } + }, + "ABOUT": { + "TITLE": "Über uns", + "EYEBROW": "3D-Druck-Labor", + "SUBTITLE": "Wir sind zwei Studenten mit viel Motivation und Lernbereitschaft.", + "HOW_TEXT": "3D Fab entstand aus Matteos anfänglichem Interesse am 3D-Druck. Er kaufte einen Drucker und begann ernsthaft zu experimentieren.\nIrgendwann kamen die ersten Anfragen: ein gebrochenes Teil zum Ersetzen, ein Ersatzteil, das man nicht findet, ein praktischer Adapter. Die Anfragen nahmen zu und wir sagten uns: okay, machen wir es richtig.\nSpäter haben wir einen Rechner entwickelt, um die Kosten im Voraus zu verstehen: das war einer der ersten Schritte vom „wir machen ein paar Teile“ zu einem echten Projekt – gemeinsam.", + "PASSIONS_TITLE": "Unsere Leidenschaften", + "PASSION_BIKE_TRIAL": "Bike Trial", + "PASSION_MOUNTAIN": "Berge", + "PASSION_SKI": "Ski", + "PASSION_SELF_HOSTING": "Self Hosting", + "PASSION_PRINT_3D": "3D-Druck", + "PASSION_TRAVEL": "Reisen", + "PASSION_SNOWBOARD": "Snowboard", + "PASSION_SNOWBOARD_INSTRUCTOR": "Snowboardlehrer", + "PASSION_ELECTRONICS": "Elektronik", + "PASSION_WOODWORKING": "Holzbearbeitung", + "PASSION_VAN_LIFE": "Van Life", + "PASSION_COFFEE": "Kaffee", + "PASSION_SOFTWARE_DEVELOPMENT": "Softwareentwicklung", + "SERVICES_TITLE": "Hauptleistungen", + "TARGET_TITLE": "Für wen", + "TARGET_TEXT": "Kleine Unternehmen, Freelancer, Tüftler und Kunden, die ein fertiges Produkt im Shop suchen.", + "TEAM_TITLE": "Unser Team", + "MEMBER_JOE_NAME": "Joe Küng", + "MEMBER_JOE_ROLE": "Informatik-Student", + "MEMBER_JOE_ALT": "Joe Küng", + "MEMBER_MATTEO_NAME": "Matteo Caletti", + "MEMBER_MATTEO_ROLE": "Elektrotechnik-Student", + "MEMBER_MATTEO_ALT": "Matteo Caletti" + }, + "LOCATIONS": { + "TITLE": "Unsere Standorte", + "SUBTITLE": "Wir sind an zwei Standorten vertreten. Wählen Sie einen Standort, um Details zu sehen.", + "TICINO": "Tessin", + "BIENNE": "Bienne", + "ADDRESS_TICINO": "Via G. Pioda 29a, Biasca", + "ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne", + "CONTACT_US": "Kontaktieren Sie uns", + "BIASCA": "Biasca" + }, + "LEGAL": { + "PRIVACY_TITLE": "Datenschutzerklärung", + "TERMS_TITLE": "Allgemeine Geschäftsbedingungen", + "LAST_UPDATE": "Letzte Aktualisierung", + "CONSENT": { + "UPLOAD_NOTICE_PREFIX": "Durch das Hochladen einer Datei akzeptieren Sie unsere", + "UPLOAD_NOTICE_LINK": "Datenschutzerklärung", + "LABEL_PREFIX": "Ich habe gelesen und akzeptiere die", + "TERMS_LINK": "Allgemeinen Geschäftsbedingungen", + "AND": "und die", + "PRIVACY_LINK": "Datenschutzerklärung", + "REQUIRED_ERROR": "Um fortzufahren müssen Sie AGB und Datenschutz akzeptieren." + }, + "PRIVACY": { + "META": { + "CONTROLLER": "Verantwortliche: Matteo Caletti und Joe Kung (3D-Fab.ch).", + "CONTACT": "Datenschutzkontakt: info@3d-fab.ch" + }, + "S1": { + "TITLE": "1. Welche Daten wir verarbeiten", + "P1": "1.1. Wir erfassen die für Angebote und Bestellungen erforderlichen Daten: Vorname, Nachname, E-Mail, Telefon, Adresse, Versand-/Rechnungsdaten und Bestelldetails.", + "P2": "1.2. Wenn Sie 3D-Dateien oder technische Anhänge hochladen, werden die Dateien nur für Analyse, Produktion, Support und Bestellverwaltung verarbeitet." + }, + "S2": { + "TITLE": "2. Zweck der Verarbeitung", + "P1": "2.1. Wir verwenden Daten ausschließlich, um: Angebote zu erstellen, Bestellungen zu bestätigen, Zahlungen zu erhalten, Versand zu organisieren und After-Sales-Support bereitzustellen.", + "P2": "2.2. Wir verwenden Daten nicht für Profiling, automatisches Marketing oder Verkauf an Dritte." + }, + "S3": { + "TITLE": "3. Speicherung von Dateien und Daten", + "P1": "3.1. Dateien, die nur für ein Angebot hochgeladen werden, werden für die Dauer der Sitzung gespeichert und bei Ablauf automatisch entfernt.", + "P2": "3.2. Dateien und Daten im Zusammenhang mit bestätigten Bestellungen werden so lange gespeichert, wie es für Produktion, Lieferung, Support und administrative/rechtliche Pflichten erforderlich ist, danach gelöscht oder minimiert.", + "P3": "3.3. Im Rechner hochgeladene Dateien werden nur für technische Analyse und Angebotsschätzung verwendet und bleiben ausschließlich mit der Rechner-Sitzung verknüpft." + }, + "S4": { + "TITLE": "4. Cookies und Tracking", + "P1": "4.1. Wir verwenden keine Profiling-, Marketing- oder Drittanbieter-Tracking-Cookies.", + "P2": "4.2. Wir verwenden keine Advertising-Tracking-Systeme. Etwaige temporäre technische Daten werden nur für den Betrieb der Sitzung genutzt." + }, + "S5": { + "TITLE": "5. Datenweitergabe", + "P1": "5.1. Wir teilen Daten nur mit für den Service strikt notwendigen Anbietern (Hosting, Zahlungen, Versand) und beschränken uns auf unerlässliche Informationen.", + "P2": "5.2. Anbieter verarbeiten Daten gemäß vertraglichen Weisungen und angemessenen Sicherheitsmaßnahmen." + }, + "S6": { + "TITLE": "6. Rechte der Nutzer", + "P1": "6.1. Sie können Auskunft, Berichtigung, Löschung oder Einschränkung der Verarbeitung Ihrer Daten verlangen, im gesetzlich vorgesehenen Rahmen.", + "P2": "6.2. Für Datenschutzanfragen schreiben Sie an info@3d-fab.ch. Die italienische Version dieser Datenschutzerklärung ist die einzige rechtlich bindende Version, sofern nicht schriftlich anders vereinbart." + } + }, + "TERMS": { + "META": { + "PROVIDER": "Anbieter: 3D-Fab.ch (Matteo Caletti und Joe Kung)", + "VERSION": "Version: v1.0", + "SCOPE": "Gültig für FDM/FFF-3D-Druck und verbundene Dienstleistungen, mit Verkauf und Lieferung ausschließlich in der Schweiz (CH)." + }, + "S1": { + "TITLE": "1. Angaben zum Anbieter und Kontakte", + "P1": "1.1. Anbieter: Matteo Caletti und Joe Kung.", + "P2": "1.2. Adresse: Lyss-strasse 71, Nidau 2560, CH.", + "P3": "1.3. E-Mail: info@3d-fab.ch." + }, + "S2": { + "TITLE": "2. Geltungsbereich", + "P1": "2.1. Diese AGB regeln 3D-Druck auf Anfrage, Zusatzleistungen (technische Beratung, CAD, Dateiprüfung, Nachbearbeitung) sowie eventuelle Standardartikel.", + "P2": "2.2. Der Anbieter verkauft und liefert ausschließlich in der Schweiz (CH).", + "P3": "2.3. Sie gelten für Bestellungen über Website, E-Mail oder andere vereinbarte Kanäle; abweichende Bedingungen des Kunden gelten nur bei schriftlicher Annahme." + }, + "S3": { + "TITLE": "3. Definitionen", + "P1": "3.1. Kunde: natürliche oder juristische Person als Käufer. Kundendateien: bereitgestellte 3D-Modelle und technische Daten. Individuelles Produkt: nach Kundenspezifikation gefertigtes Teil. Bestellung: vom Anbieter angenommene Anfrage." + }, + "S4": { + "TITLE": "4. Vertragsschluss und Bestellung", + "P1": "4.1. Der Vertrag kommt mit Auftragsbestätigung (E-Mail/Portal) oder mit Produktionsstart nach Zahlung/Anzahlung zustande.", + "P2": "4.2. Automatische Angebote können nach minimaler technischer Prüfung (Druckbarkeit, Stützen, Maschinenlimits) bestätigt oder aktualisiert werden.", + "P3": "4.3. Der Anbieter kann technisch nicht umsetzbare oder nicht konforme Bestellungen ablehnen." + }, + "S5": { + "TITLE": "5. Preise, Steuern und Versand", + "P1": "5.1. Die Preise sind in CHF, sofern nicht anders angegeben bezüglich MwSt. inkl./exkl..", + "P2": "5.2. Versand und Verpackung werden, sofern anwendbar, separat ausgewiesen.", + "P3": "5.3. Für Kleinserien oder komplexes CAD können schriftliche Angebote mit spezifischen Bedingungen gelten (Muster, Staffelungen, Freigabe Erstteil)." + }, + "S6": { + "TITLE": "6. Zahlungen", + "P1": "6.1. Akzeptierte Methoden: TWINT und Banküberweisung.", + "P2": "6.2. Sofern nicht anders vereinbart, startet die Produktion erst nach Zahlung.", + "P3": "6.3. Für CAD-Beratung und Kleinserien kann eine Anzahlung (30-100%) und/oder Restzahlung vor Lieferung verlangt werden.", + "P4": "6.4. Überweisungsdaten: Joe Kung, IBAN CH74 0900 0000 1548 2158 1, Via G. Pioda 29a, 6710 Biasca." + }, + "S7": { + "TITLE": "7. Kundendateien und technische Verantwortung", + "P1": "7.1. Der Kunde garantiert, die Rechte an den Dateien zu haben und dass deren Nutzung keine Rechte Dritter verletzt (Urheberrecht, Patente, Lizenzen, Geschäftsgeheimnisse).", + "P2": "7.2. Der Kunde ist verantwortlich für Modellkorrektheit, Materialwahl, Eignung für den Endgebrauch und Einhaltung der anwendbaren Normen.", + "P3": "7.3. Der Anbieter kann Änderungen zur Verbesserung von Druckbarkeit und Ergebnis vorschlagen, übernimmt jedoch keine Zertifizierungsfunktion für das Endprodukt, außer bei schriftlicher Vereinbarung." + }, + "S8": { + "TITLE": "8. FDM/FFF-Qualität und Toleranzen", + "P1": "8.1. FDM/FFF-Druck hat intrinsische Eigenschaften: Schichtlinien, mechanische Anisotropie, Mikro-Unvollkommenheiten, Farbabweichungen und mögliche Schrumpfung/Verzug in Abhängigkeit von Geometrie und Material.", + "P2": "8.2. Standardtoleranzen (sofern nicht schriftlich anders vereinbart): bis 100 mm +/-0.3 mm; über 100 mm +/-0.5% (mindestens +/-0.3 mm).", + "P3": "8.3. Kritische ästhetische oder dimensionale Anforderungen müssen vor der Bestellung vereinbart werden (z. B. Muster, Kontrollmaße, spezifische Oberflächen)." + }, + "S9": { + "TITLE": "9. Nachbearbeitung und Zusatzarbeiten", + "P1": "9.1. Arbeiten wie Stützstrukturen entfernen, Schleifen, Grundieren/Lackieren oder Gewindeeinsätze erfolgen nur nach Vereinbarung und können dimensionale oder optische Abweichungen verursachen.", + "P2": "9.2. Auf Anfrage kann eine Freigabe des ersten Teils oder Musters vorgesehen werden, ggf. kostenpflichtig." + }, + "S10": { + "TITLE": "10. Produktions- und Lieferzeiten", + "P1": "10.1. Die angegebenen Zeiten sind Schätzungen basierend auf Auslastung, Komplexität und Materialverfügbarkeit.", + "P2": "10.2. Verzögerungen durch externe Ursachen (Kuriere, Lieferanten, Ausfälle, höhere Gewalt) begründen keinen automatischen Anspruch auf Vertragsstrafen, außer bei schriftlicher Vereinbarung.", + "P3": "10.3. Der Kunde muss korrekte und vollständige Adressen angeben; etwaige Kosten für erneute Zustellung aufgrund falscher Adresse trägt der Kunde." + }, + "S11": { + "TITLE": "11. Widerrufsrecht und Stornierung", + "P1": "11.1. Sofern nicht schriftlich bestätigte Ausnahmen vorliegen, besteht nach Bestellung kein Widerrufs- oder Rückgaberecht.", + "P2": "11.2. Individuelle Produkte sind nach Produktionsstart nicht stornierbar oder erstattbar.", + "P3": "11.3. Der Anbieter kann Ausnahmen vor Produktionsstart akzeptieren und bereits entstandene Kosten einbehalten.", + "P4": "11.4. Etwaige Sonderbedingungen müssen im Angebot, in der Auftragsbestätigung oder in schriftlicher Kommunikation festgehalten sein." + }, + "S12": { + "TITLE": "12. Reklamationen, Mängel und Rechtsbehelfe", + "P1": "12.1. Der Kunde muss die Produkte bei Lieferung prüfen und eventuelle Mängel innerhalb von 7 Tagen schriftlich mit Foto/Video und Beschreibung melden.", + "P2": "12.2. Typische FDM-Merkmale, kleine Farbabweichungen, nicht-funktionale Unvollkommenheiten oder Toleranzen innerhalb der vereinbarten Grenzen gelten nicht automatisch als Mangel.", + "P3": "12.3. Bei einem vom Anbieter zu vertretenden Mangel sind die Rechtsbehelfe nach Wahl des Anbieters: Neudruck/Ersatz oder Rückerstattung begrenzt auf den Wert des mangelhaften Teils bzw. der Bestellung.", + "P4": "12.4. Vor Neudruck oder Rückerstattung kann die Rückgabe des Teils verlangt werden; wird der Mangel bestätigt, trägt der Anbieter die Rücksendekosten." + }, + "S13": { + "TITLE": "13. Verbotene Nutzungen und Konformität", + "P1": "13.1. Der Anbieter kann Bestellungen zu illegalen Objekten, Waffen oder regulierten Teilen sowie sicherheitskritischen oder medizinischen Anwendungen ohne spezielle Vereinbarungen und Validierungen ablehnen.", + "P2": "13.2. Der Kunde bleibt für den Endgebrauch und die regulatorische Konformität des Produkts verantwortlich." + }, + "S14": { + "TITLE": "14. Geistiges Eigentum und Lizenzen", + "P1": "14.1. Rechte an Kundendateien bleiben beim Kunden bzw. den jeweiligen Rechteinhabern. Der Kunde gewährt dem Anbieter eine auf technische Bewertung und Produktion beschränkte Lizenz.", + "P2": "14.2. Sofern nicht anders vereinbart, werden vom Anbieter entwickelte Dateien und CAD-Projekte nach Zahlung mit Nutzungsrecht für die vereinbarten Zwecke übergeben.", + "P3": "14.3. Der Kunde stellt den Anbieter von Ansprüchen Dritter im Zusammenhang mit vom Kunden bereitgestellten Dateien oder Anweisungen frei." + }, + "S15": { + "TITLE": "15. Datenschutz", + "P1": "15.1. Der Anbieter verarbeitet personenbezogene Daten für Bestellverwaltung, Zahlungen, Versand und Support.", + "P2": "15.2. Daten können nur im erforderlichen Umfang zur Leistungserbringung mit technischen Anbietern und Kurieren geteilt werden." + }, + "S16": { + "TITLE": "16. Haftungsbeschränkung", + "P1": "16.1. Im gesetzlichen Rahmen haftet der Anbieter nur für vorhersehbare direkte Schäden und in jedem Fall nicht über den Auftragswert des betroffenen Produkts oder der beanstandeten Dienstleistung hinaus.", + "P2": "16.2. Mittelbare Schäden, entgangener Gewinn, Betriebsunterbrechung, Datenverlust und Folgeschäden sind im zulässigen Rahmen ausgeschlossen.", + "P3": "16.3. Gesetzlich nicht ausschließbare Haftungen bleiben unberührt (z. B. Vorsatz oder grobe Fahrlässigkeit)." + }, + "S17": { + "TITLE": "17. Höhere Gewalt", + "P1": "17.1. Ereignisse außerhalb der zumutbaren Kontrolle des Anbieters (Ausfälle, Blackout, Lieferverzögerungen, Streiks, behördliche Maßnahmen) können zu Fristverlängerungen oder Aussetzungen ohne Haftung führen." + }, + "S18": { + "TITLE": "18. Anwendbares Recht und Gerichtsstand", + "P1": "18.1. Es gilt schweizerisches Recht.", + "P2": "18.2. Gerichtsstand: Sitz des Anbieters, vorbehaltlich zwingender Verbraucherschutzvorschriften.", + "P3": "18.3. Bei Auslegungsunterschieden gilt die italienische Version dieser Bedingungen und ist die einzige rechtlich bindende Version, sofern nicht schriftlich anders vereinbart." + } + }, + "TERMS_UPDATE_DATE": "24. Februar 2026", + "PRIVACY_UPDATE_DATE": "24. Februar 2026" + }, + "CONTACT": { + "TITLE": "Kontaktieren Sie uns", + "SEND": "Nachricht senden", + "REQ_TYPE_LABEL": "Anfrageart", + "TYPE_PRIVATE": "Privat", + "TYPE_COMPANY": "Unternehmen", + "REQ_TYPE_CUSTOM": "Individuelles Angebot", + "REQ_TYPE_SERIES": "Serienfertigung", + "REQ_TYPE_CONSULT": "Beratung", + "REQ_TYPE_QUESTION": "Allgemeine Fragen", + "PHONE": "Telefon", + "IS_COMPANY": "Sind Sie ein Unternehmen?", + "COMPANY_NAME": "Firmenname", + "REF_PERSON": "Ansprechperson", + "UPLOAD_LABEL": "Anhänge", + "UPLOAD_HINT": "Max. 15 Dateien. Unterstützt: Bilder, Videos, PDF, Office-Dokumente, STL/STEP/3MF/OBJ/IGES, DWG/DXF. Komprimierte Dateien sind nicht erlaubt.", + "DROP_FILES": "Dateien hier ablegen oder klicken zum Hochladen", + "PLACEHOLDER_NAME": "Ihr Name", + "PLACEHOLDER_EMAIL": "ihre@email.com", + "PLACEHOLDER_PHONE": "+41 00 000 00 00", + "PLACEHOLDER_COMPANY": "Firmenname", + "PLACEHOLDER_REF_PERSON": "Ansprechperson", + "LABEL_MESSAGE": "Nachricht *", + "LABEL_EMAIL": "E-Mail *", + "LABEL_NAME": "Name *", + "MSG_SENT": "Gesendet!", + "ERR_MAX_FILES": "Maximallimit von 15 Dateien erreicht.", + "ERR_COMPRESSED_FILES": "Komprimierte Dateien sind nicht erlaubt (ZIP/RAR/7z/TAR/GZ).", + "SUCCESS_TITLE": "Nachricht erfolgreich gesendet", + "SUCCESS_DESC": "Vielen Dank für Ihre Kontaktaufnahme. Wir haben Ihre Nachricht erhalten und senden Ihnen in Kürze eine Zusammenfassungs-E-Mail.", + "SEND_ANOTHER": "Weitere Nachricht senden", + "FILE_TYPE_PDF": "PDF", + "FILE_TYPE_3D": "3D", + "FILE_TYPE_VIDEO": "Video", + "FILE_TYPE_DOC": "DOC", + "FILE_TYPE_FILE": "DATEI", + "ERROR_SUBMIT": "Fehler beim Senden der Anfrage. Bitte versuchen Sie es erneut.", + "REMOVE_FILE": "Angehängte Datei entfernen", + "HERO_SUBTITLE": "Wir sind hier, um Ihnen zu helfen. Füllen Sie das untenstehende Formular für jede Anfrage aus." + }, + "CHECKOUT": { + "TITLE": "Checkout", + "SUBTITLE": "Schließen Sie Ihre Bestellung ab, indem Sie Versand- und Zahlungsdetails eingeben.", + "CONTACT_INFO": "Kontaktinformationen", + "BILLING_ADDR": "Rechnungsadresse", + "SHIPPING_ADDR": "Lieferadresse", + "FIRST_NAME": "Vorname", + "LAST_NAME": "Nachname", + "EMAIL": "E-Mail", + "PHONE": "Telefon", + "COMPANY_NAME": "Firmenname", + "ADDRESS_1": "Adresse (Straße und Nummer)", + "ADDRESS_2": "Zusätzliche Informationen (optional)", + "ZIP": "PLZ", + "CITY": "Ort", + "COUNTRY": "Land", + "SHIPPING_SAME": "Die Lieferadresse ist gleich der Rechnungsadresse", + "PLACE_ORDER": "Bestellung absenden", + "PROCESSING": "Verarbeitung...", + "SUMMARY_TITLE": "Bestellübersicht", + "SUBTOTAL": "Zwischensumme", + "ITEMS_BASE_SUBTOTAL": "Artikelbasis-Zwischensumme", + "MACHINE_COST": "Maschinenkosten", + "SETUP_FEE": "Einrichtungskosten", + "TOTAL": "Gesamt", + "QTY": "Menge", + "PER_PIECE": "pro Stück", + "SHIPPING": "Versand (CH)", + "ERR_NO_SESSION_START": "Keine aktive Sitzung gefunden. Bitte starten Sie ein neues Angebot.", + "ERR_LOAD_SESSION": "Sitzungsdetails konnten nicht geladen werden. Bitte erneut versuchen.", + "ERR_NO_SESSION_CREATE_ORDER": "Keine aktive Sitzung gefunden. Bestellung kann nicht erstellt werden.", + "ERR_CREATE_ORDER": "Bestellung konnte nicht erstellt werden. Bitte erneut versuchen.", + "INVALID_EMAIL": "Ungültige E-Mail", + "COMPANY_OPTIONAL": "Firmenname (Optional)", + "REF_PERSON_OPTIONAL": "Ansprechperson (Optional)", + "SHIPPING_CALCULATED_NEXT_STEP": "Versandkosten werden im nächsten Schritt berechnet", + "EXCLUDES_SHIPPING": "Versandkosten ausgeschlossen" + }, + "PAYMENT": { + "TITLE": "Zahlung", + "METHOD": "Zahlungsmethode", + "TWINT_TITLE": "Mit TWINT bezahlen", + "TWINT_DESC": "Scannen Sie den Code mit der TWINT-App, auf Mobilgeräten klicken Sie auf die Schaltfläche.", + "TWINT_OPEN": "Direkt in TWINT öffnen", + "TWINT_LINK": "Zahlungslink öffnen", + "BANK_TITLE": "Banküberweisung", + "BANK_OWNER": "Kontoinhaber", + "BANK_IBAN": "IBAN", + "BANK_REF": "Referenz", + "BILLING_INFO_HINT": "Wir haben die Felder für Sie ausgefüllt, bitte den Zahlungszweck nicht ändern", + "DOWNLOAD_QR": "QR-Rechnung herunterladen (PDF)", + "DOWNLOAD_CONFIRMATION": "Bestätigung herunterladen (PDF)", + "CONFIRM": "Ich habe die Zahlung abgeschlossen", + "SUMMARY_TITLE": "Bestellübersicht", + "SUBTOTAL": "Zwischensumme", + "SHIPPING": "Versand", + "SETUP_FEE": "Einrichtungskosten", + "TOTAL": "Gesamt", + "LOADING": "Bestelldetails werden geladen...", + "METHOD_TWINT": "TWINT", + "METHOD_BANK": "QR-Rechnung / Überweisung", + "STATUS_REPORTED_TITLE": "Bestellung in Bearbeitung", + "STATUS_REPORTED_DESC": "Wir haben Ihren Vorgang registriert. Sobald wir die Zahlung bestätigen, geht die Bestellung in Produktion.", + "IN_VERIFICATION": "Zahlung gemeldet", + "TWINT_QR_ALT": "TWINT-Zahlungs-QR", + "TWINT_BUTTON_ALT": "Eingebettete TWINT-Schaltfläche" + }, + "TRACKING": { + "TITLE": "Bestellstatus", + "SUBTITLE": "Prüfen Sie den Status Ihrer Bestellung und verwalten Sie bei Bedarf die Zahlung.", + "STEP_PENDING": "Ausstehend", + "STEP_REPORTED": "In Prüfung", + "STEP_PRODUCTION": "In Produktion", + "STEP_SHIPPED": "Versendet" + }, + "ORDER_CONFIRMED": { + "TITLE": "Bestellung bestätigt", + "SUBTITLE": "Zahlung erfasst. Ihre Bestellung wird nun bearbeitet.", + "STATUS": "In Bearbeitung", + "HEADING": "Wir bereiten Ihre Bestellung vor", + "ORDER_REF": "Bestellreferenz", + "PROCESSING_TEXT": "Sobald wir die Zahlung bestätigen, geht Ihre Bestellung in Produktion.", + "EMAIL_TEXT": "Wir senden Ihnen eine E-Mail mit Statusupdate und nächsten Schritten.", + "BACK_HOME": "Zur Startseite" + }, + "STL_VIEWER": { + "LOADING": "3D-Modell wird geladen..." + }, + "HOME": { + "SHOP_GALLERY_ARIA": "Produktgalerie Shop", + "FOUNDER_PREV_ARIA": "Vorheriges Foto", + "FOUNDER_NEXT_ARIA": "Nächstes Foto", + "SHOP_IMAGE_ALT_1": "Technisches 3D-gedrucktes Produkt", + "FOUNDER_IMAGE_ALT_1": "Gründer - Foto 1", + "FOUNDER_IMAGE_ALT_2": "Gründer - Foto 2", + "HERO_EYEBROW": "Technischer 3D-Druck für Unternehmen, Freelancer und Maker", + "HERO_TITLE": "Preis und Lieferzeit in wenigen Sekunden.
Von der 3D-Datei zum fertigen Teil.", + "HERO_LEAD": "Der fortschrittlichste Rechner für Ihre 3D-Drucke: maximale Präzision und keine Überraschungen.", + "HERO_SUBTITLE": "Wir bieten auch CAD-Services für individuelle Teile an!", + "BTN_CALCULATE": "Angebot berechnen", + "BTN_SHOP": "Zum Shop", + "BTN_CONTACT": "Mit uns sprechen", + "SEC_CALC_TITLE": "Korrekte Preisberechnung in wenigen Sekunden", + "SEC_CALC_SUBTITLE": "Keine Registrierung erforderlich. Die Schätzung basiert auf echtem Slicing.", + "SEC_CALC_LIST_1": "Unterstützte Formate: STL, 3MF, STEP", + "CARD_CALC_EYEBROW": "Automatische Berechnung", + "CARD_CALC_TITLE": "Preis und Lieferzeit mit einem Klick", + "CARD_CALC_TAG": "Ohne Registrierung", + "CARD_CALC_STEP_1": "3D-Datei hochladen", + "CARD_CALC_STEP_2": "Material und Qualität wählen", + "CARD_CALC_STEP_3": "Kosten und Zeit sofort erhalten", + "BTN_OPEN_CALC": "Rechner öffnen", + "SEC_CAP_TITLE": "Was Sie erhalten können", + "SEC_CAP_SUBTITLE": "Maßgeschneiderte Produktion für Prototypen, Kleinserien und individuelle Teile.", + "CAP_1_TITLE": "Schnelles Prototyping", + "CAP_1_TEXT": "Von der digitalen Datei zum physischen Modell in 24/48 Stunden. Prüfen Sie Ergonomie, Passungen und Funktion vor der finalen Form.", + "CAP_2_TITLE": "Individuelle Teile", + "CAP_2_TEXT": "Einzigartige Komponenten, die am Markt schwer zu finden sind. Wir reproduzieren defekte Teile oder erstellen maßgeschneiderte Anpassungen.", + "CAP_3_TITLE": "Kleinserien", + "CAP_3_TEXT": "Brückenproduktion oder limitierte Serien (10-500 Stück) mit reproduzierbarer Qualität.", + "CAP_4_TITLE": "Beratung und CAD", + "CAP_4_TEXT": "Sie haben noch keine 3D-Datei? Wir helfen beim Entwurf, bei der Druckoptimierung und bei der Auswahl des richtigen Materials.", + "SEC_SHOP_TITLE": "Shop", + "SEC_SHOP_TEXT": "Ausgewählte Produkte, einsatzbereit.", + "SEC_SHOP_LIST_1": "Von uns entwickelte Produkte", + "SEC_SHOP_LIST_2": "Ersatzteile und Komponenten, die schwer zu beschaffen sind", + "SEC_SHOP_LIST_3": "Halterungen und Organizer zur Optimierung Ihrer Arbeitsabläufe", + "BTN_DISCOVER": "Produkte entdecken", + "BTN_REQ_SOLUTION": "Lösung anfragen", + "CARD_SHOP_1_TITLE": "Auswahl geprüfter Produkte", + "CARD_SHOP_1_TEXT": "Geprüft, um langfristige Funktionalität und Stabilität zu gewährleisten.", + "CARD_SHOP_2_TITLE": "Einsatzfertige Kits", + "CARD_SHOP_2_TEXT": "Kompatible Komponenten, leicht montierbar und ohne Überraschungen.", + "CARD_SHOP_3_TITLE": "Auf Anfrage", + "CARD_SHOP_3_TEXT": "Sie finden nicht, was Sie brauchen? Wir entwickeln und produzieren es für Sie.", + "SEC_ABOUT_TITLE": "Über uns", + "SEC_ABOUT_TEXT": "Wir sind zwei Ingenieurstudenten: 3D-Druck hat uns aus einem einfachen Grund begeistert – ein Problem sehen und die Lösung bauen. Aus dieser Idee entstehen Prototypen und Objekte, die im Alltag funktionieren.", + "FOUNDERS_PHOTO": "Foto der Gründer" + }, + "ORDER": { + "ERR_ID_NOT_FOUND": "Bestell-ID nicht gefunden.", + "ERR_LOAD_ORDER": "Bestelldetails konnten nicht geladen werden.", + "ERR_REPORT_PAYMENT": "Zahlung konnte nicht gemeldet werden. Bitte erneut versuchen.", + "NOT_AVAILABLE": "N/V" + }, + "DROPZONE": { + "DEFAULT_LABEL": "Dateien hierher ziehen oder klicken zum Hochladen", + "DEFAULT_SUBTEXT": "Unterstützt .STL, .3MF, .STEP" + }, + "COLOR": { + "AVAILABLE_COLORS": "Verfügbare Farben", + "CATEGORY_GLOSSY": "Glänzend", + "CATEGORY_MATTE": "Matt", + "NAME": { + "BLACK": "Schwarz", + "WHITE": "Weiß", + "RED": "Rot", + "BLUE": "Blau", + "GREEN": "Grün", + "YELLOW": "Gelb", + "MATTE_BLACK": "Matt Schwarz", + "MATTE_WHITE": "Matt Weiß", + "MATTE_GRAY": "Matt Grau" + } + }, + "COMMON": { + "REQUIRED": "Pflichtfeld", + "INVALID_EMAIL": "Ungültige E-Mail", + "BACK": "Zurück", + "OPTIONAL": "(Optional)" + } +} diff --git a/frontend/src/assets/i18n/en.json b/frontend/src/assets/i18n/en.json index 11de056..cb443ef 100644 --- a/frontend/src/assets/i18n/en.json +++ b/frontend/src/assets/i18n/en.json @@ -4,7 +4,8 @@ "CALCULATOR": "Calculator", "SHOP": "Shop", "ABOUT": "About Us", - "CONTACT": "Contact Us" + "CONTACT": "Contact Us", + "LANGUAGE_SELECTOR": "Language selector" }, "QUOTE": { "CONSULT": "Request Consultation", @@ -214,7 +215,7 @@ "S6": { "TITLE": "6. User rights", "P1": "6.1. You can request access, rectification, deletion or restriction of processing of your data, within the limits provided by law.", - "P2": "6.2. For any privacy request write to info@3d-fab.ch." + "P2": "6.2. For any privacy request write to info@3d-fab.ch. The Italian version of this privacy policy is the only legally binding version, unless otherwise agreed in writing." } }, "TERMS": { diff --git a/frontend/src/assets/i18n/fr.json b/frontend/src/assets/i18n/fr.json new file mode 100644 index 0000000..1dcf7f7 --- /dev/null +++ b/frontend/src/assets/i18n/fr.json @@ -0,0 +1,546 @@ +{ + "NAV": { + "HOME": "Accueil", + "CALCULATOR": "Calculateur", + "SHOP": "Boutique", + "ABOUT": "Qui sommes-nous", + "CONTACT": "Contactez-nous", + "LANGUAGE_SELECTOR": "Sélecteur de langue" + }, + "FOOTER": { + "PRIVACY": "Confidentialité", + "TERMS": "Conditions générales", + "CONTACT": "Contactez-nous" + }, + "HOME": { + "HERO_EYEBROW": "Impression 3D technique pour entreprises, freelances et makers", + "HERO_TITLE": "Prix et délais en quelques secondes.
Du fichier 3D à la pièce finie.", + "HERO_LEAD": "Le calculateur le plus avancé pour vos impressions 3D : précision totale et zéro surprise.", + "HERO_SUBTITLE": "Nous proposons aussi des services CAD pour des pièces personnalisées !", + "BTN_CALCULATE": "Calculer un devis", + "BTN_SHOP": "Aller à la boutique", + "BTN_CONTACT": "Parlez avec nous", + "SEC_CALC_TITLE": "Prix correct en quelques secondes", + "SEC_CALC_SUBTITLE": "Aucune inscription requise. L'estimation est effectuée via un vrai slicing.", + "SEC_CALC_LIST_1": "Formats pris en charge : STL, 3MF, STEP", + "CARD_CALC_EYEBROW": "Calcul automatique", + "CARD_CALC_TITLE": "Prix et délais en un clic", + "CARD_CALC_TAG": "Sans inscription", + "CARD_CALC_STEP_1": "Chargez le fichier 3D", + "CARD_CALC_STEP_2": "Choisissez le matériau et la qualité", + "CARD_CALC_STEP_3": "Recevez immédiatement coût et délai", + "BTN_OPEN_CALC": "Ouvrir le calculateur", + "SEC_CAP_TITLE": "Ce que vous pouvez obtenir", + "SEC_CAP_SUBTITLE": "Production sur mesure pour prototypes, petites séries et pièces personnalisées.", + "CAP_1_TITLE": "Prototypage rapide", + "CAP_1_TEXT": "Du fichier numérique au modèle physique en 24/48 heures. Vérifiez ergonomie, emboîtements et fonctionnement avant le moule définitif.", + "CAP_2_TITLE": "Pièces personnalisées", + "CAP_2_TEXT": "Composants uniques introuvables dans le commerce. Nous reproduisons des pièces cassées ou créons des adaptations sur mesure.", + "CAP_3_TITLE": "Petites séries", + "CAP_3_TEXT": "Production intermédiaire ou séries limitées (10-500 pièces) avec qualité reproductible.", + "CAP_4_TITLE": "Conseil et CAD", + "CAP_4_TEXT": "Vous n'avez pas de fichier 3D ? Nous vous aidons à le concevoir, à l'optimiser pour l'impression et à choisir le bon matériau ensemble.", + "SEC_SHOP_TITLE": "Boutique", + "SEC_SHOP_TEXT": "Produits sélectionnés et prêts à l'emploi.", + "SEC_SHOP_LIST_1": "Produits conçus par nous", + "SEC_SHOP_LIST_2": "Pièces de rechange et composants difficiles à trouver", + "SEC_SHOP_LIST_3": "Supports et organiseurs pour améliorer les flux de travail", + "BTN_DISCOVER": "Découvrir les produits", + "BTN_REQ_SOLUTION": "Demander une solution", + "CARD_SHOP_1_TITLE": "Sélection de produits vérifiés", + "CARD_SHOP_1_TEXT": "Contrôlés pour garantir fonctionnalité et stabilité dans le temps.", + "CARD_SHOP_2_TITLE": "Kits prêts à l'emploi", + "CARD_SHOP_2_TEXT": "Composants compatibles et faciles à monter, sans surprise.", + "CARD_SHOP_3_TITLE": "Sur demande", + "CARD_SHOP_3_TEXT": "Vous ne trouvez pas ce qu'il vous faut ? Nous le concevons et le produisons pour vous.", + "SEC_ABOUT_TITLE": "À propos de nous", + "SEC_ABOUT_TEXT": "Nous sommes deux étudiants en ingénierie : l'impression 3D nous a conquis pour une raison simple, voir un problème et construire la solution. De cette idée naissent des prototypes et des objets conçus pour fonctionner au quotidien.", + "FOUNDERS_PHOTO": "Photo des fondateurs", + "SHOP_GALLERY_ARIA": "Galerie produits boutique", + "FOUNDER_PREV_ARIA": "Photo précédente", + "FOUNDER_NEXT_ARIA": "Photo suivante", + "SHOP_IMAGE_ALT_1": "Produit technique imprimé en 3D", + "FOUNDER_IMAGE_ALT_1": "Fondateur - photo 1", + "FOUNDER_IMAGE_ALT_2": "Fondateur - photo 2" + }, + "CALC": { + "TITLE": "Calculer un devis 3D", + "SUBTITLE": "Chargez votre fichier 3D (STL, 3MF, STEP), réglez la qualité et la couleur puis calculez immédiatement prix et délais.", + "CTA_START": "Commencer maintenant", + "BUSINESS": "Entreprises", + "PRIVATE": "Particuliers", + "MODE_EASY": "Base", + "MODE_ADVANCED": "Avancée", + "UPLOAD_LABEL": "Glissez votre fichier 3D ici", + "UPLOAD_SUB": "Nous prenons en charge STL, 3MF, STEP jusqu'à 50MB", + "MATERIAL": "Matériau", + "QUALITY": "Qualité", + "PRINT_SPEED": "Vitesse d'impression", + "QUANTITY": "Quantité", + "NOTES": "Notes supplémentaires", + "COLOR": "Couleur", + "INFILL": "Remplissage (%)", + "PATTERN": "Motif de remplissage", + "LAYER_HEIGHT": "Hauteur de couche", + "NOZZLE": "Diamètre de buse", + "SUPPORT": "Supports", + "SUPPORT_DESC": "Activer les supports pour les surplombs", + "CALCULATE": "Calculer le devis", + "RESULT": "Devis estimé", + "TIME": "Temps d'impression", + "MACHINE_COST": "Coût machine", + "COST": "Coût total", + "ORDER": "Commander maintenant", + "CONSULT": "Demander une consultation", + "ERROR_GENERIC": "Une erreur s'est produite pendant le calcul du devis.", + "NEW_QUOTE": "Calculer un nouveau devis", + "ORDER_SUCCESS_TITLE": "Commande envoyée avec succès", + "ORDER_SUCCESS_DESC": "Nous avons reçu les détails de votre commande. Vous recevrez bientôt un e-mail de confirmation avec les informations de paiement.", + "BENEFITS_TITLE": "Pourquoi nous choisir ?", + "BENEFITS_1": "Devis automatique avec coût et délai immédiats", + "BENEFITS_2": "Matériaux sélectionnés et qualité contrôlée", + "BENEFITS_3": "Conseil CAD si le fichier nécessite des modifications", + "ERR_FILE_REQUIRED": "Le fichier est obligatoire.", + "ANALYZING_TITLE": "Analyse en cours...", + "ANALYZING_TEXT": "Nous analysons la géométrie et calculons le parcours outil.", + "QTY_SHORT": "QTÉ", + "COLOR_LABEL": "COULEUR", + "ADD_FILES": "Ajouter des fichiers", + "UPLOADING": "Téléversement...", + "PROCESSING": "Traitement...", + "NOTES_PLACEHOLDER": "Instructions spécifiques...", + "SETUP_NOTE": "* Inclut {{cost}} comme coût de setup", + "SHIPPING_NOTE": "** Frais d'expédition exclus, calculés à l'étape suivante", + "STEP_WARNING": "La visualisation 3D n'est pas compatible avec les fichiers STEP et 3MF", + "REMOVE_FILE": "Supprimer le fichier", + "FALLBACK_MATERIAL": "PLA (fallback)", + "FALLBACK_QUALITY_STANDARD": "Standard", + "ERR_FILE_TOO_LARGE": "Certains fichiers dépassent la limite de 200MB et n'ont pas été ajoutés." + }, + "QUOTE": { + "PROCEED_ORDER": "Procéder à la commande", + "CONSULT": "Demander une consultation", + "TOTAL": "Total", + "MAX_QTY_NOTICE": "Pour des quantités supérieures à {{max}} pièces, demandez une consultation." + }, + "USER_DETAILS": { + "TITLE": "Vos données", + "NAME": "Prénom", + "NAME_PLACEHOLDER": "Votre prénom", + "SURNAME": "Nom", + "SURNAME_PLACEHOLDER": "Votre nom", + "EMAIL": "E-mail", + "EMAIL_PLACEHOLDER": "votre@email.com", + "PHONE": "Téléphone", + "PHONE_PLACEHOLDER": "+41 ...", + "ADDRESS": "Adresse", + "ADDRESS_PLACEHOLDER": "Rue et numéro", + "ZIP": "Code postal", + "ZIP_PLACEHOLDER": "0000", + "CITY": "Ville", + "CITY_PLACEHOLDER": "Ville", + "SUBMIT": "Continuer", + "SUMMARY_TITLE": "Récapitulatif", + "DEFAULT_COLOR": "Par défaut" + }, + "COMMON": { + "REQUIRED": "Champ obligatoire", + "INVALID_EMAIL": "E-mail invalide", + "BACK": "Retour", + "OPTIONAL": "(Optionnel)" + }, + "SHOP": { + "TITLE": "Solutions techniques", + "SUBTITLE": "Produits prêts à l'emploi qui résolvent des problèmes pratiques", + "WIP_EYEBROW": "Work in progress", + "WIP_TITLE": "Boutique en préparation", + "WIP_SUBTITLE": "Nous préparons une boutique avec des produits sélectionnés et des fonctionnalités de création automatique !", + "WIP_CTA_CALC": "Aller au calculateur", + "WIP_RETURN_LATER": "Revenez dans un moment", + "WIP_NOTE": "Nous tenons à bien faire les choses : en attendant, vous pouvez calculer immédiatement prix et délais d'un fichier 3D avec notre calculateur.", + "ADD_CART": "Ajouter au panier", + "BACK": "Retour à la boutique", + "NOT_FOUND": "Produit introuvable.", + "DETAILS": "Détails", + "MOCK_ADD_CART": "Ajouté au panier (Mock)", + "SUCCESS_TITLE": "Ajouté au panier", + "SUCCESS_DESC": "Le produit a été ajouté au panier avec succès.", + "CONTINUE": "Continuer", + "CATEGORIES": { + "FILAMENTS": "Filaments", + "ACCESSORIES": "Accessoires" + }, + "PRODUCTS": { + "P1": { + "NAME": "Filament PLA Standard", + "DESC": "Le classique pour chaque impression, simple et fiable." + }, + "P2": { + "NAME": "Filament PETG Tough", + "DESC": "Résistant aux chocs et aux températures." + }, + "P3": { + "NAME": "Kit de buses (0.4mm)", + "DESC": "Kit de remplacement pour extrudeur FDM." + } + } + }, + "ABOUT": { + "TITLE": "Qui sommes-nous", + "EYEBROW": "Atelier d'impression 3D", + "SUBTITLE": "Nous sommes deux étudiants avec beaucoup d'envie de faire et d'apprendre.", + "HOW_TEXT": "3D Fab est né de l'intérêt initial de Matteo pour l'impression 3D. Il a acheté une imprimante et a commencé à expérimenter sérieusement. \n À un certain moment, les premières demandes sont arrivées : une pièce cassée à remplacer, une pièce de rechange introuvable, un adaptateur pratique à avoir. Les demandes ont augmenté et nous nous sommes dit : d'accord, faisons-le bien.\nEnsuite, nous avons créé un calculateur pour connaître le coût à l'avance : cela a été l'un des premiers pas qui nous a fait passer de « on fait quelques pièces » à un vrai projet, ensemble.", + "PASSIONS_TITLE": "Nos passions", + "PASSION_BIKE_TRIAL": "Bike trial", + "PASSION_MOUNTAIN": "Montagne", + "PASSION_SKI": "Ski", + "PASSION_SELF_HOSTING": "Self hosting", + "PASSION_PRINT_3D": "Impression 3D", + "PASSION_TRAVEL": "Voyage", + "PASSION_SNOWBOARD": "Snowboard", + "PASSION_SNOWBOARD_INSTRUCTOR": "Moniteur de snowboard", + "PASSION_ELECTRONICS": "Électronique", + "PASSION_WOODWORKING": "Travail du bois", + "PASSION_VAN_LIFE": "Van life", + "PASSION_COFFEE": "Café", + "PASSION_SOFTWARE_DEVELOPMENT": "Développement logiciel", + "SERVICES_TITLE": "Services principaux", + "TARGET_TITLE": "Pour qui", + "TARGET_TEXT": "Petites entreprises, freelances, makers et clients qui cherchent un produit prêt à l'emploi dans la boutique.", + "TEAM_TITLE": "Notre équipe", + "MEMBER_JOE_NAME": "Joe Küng", + "MEMBER_JOE_ROLE": "Étudiant en ingénierie informatique", + "MEMBER_JOE_ALT": "Joe Küng", + "MEMBER_MATTEO_NAME": "Matteo Caletti", + "MEMBER_MATTEO_ROLE": "Étudiant en ingénierie électronique", + "MEMBER_MATTEO_ALT": "Matteo Caletti" + }, + "LOCATIONS": { + "TITLE": "Nos sites", + "SUBTITLE": "Nous sommes présents sur deux sites. Sélectionnez le site pour voir les détails.", + "TICINO": "Tessin", + "BIASCA": "Biasca", + "BIENNE": "Bienne", + "ADDRESS_TICINO": "Via G. Pioda 29a, Biasca", + "ADDRESS_BIENNE": "Lyss-strasse 71, Nidau 2560 Bienne", + "CONTACT_US": "Contactez-nous" + }, + "LEGAL": { + "PRIVACY_TITLE": "Politique de confidentialité", + "TERMS_TITLE": "Conditions générales", + "LAST_UPDATE": "Dernière mise à jour", + "TERMS_UPDATE_DATE": "24 février 2026", + "PRIVACY_UPDATE_DATE": "24 février 2026", + "CONSENT": { + "LABEL_PREFIX": "J'ai lu et j'accepte les", + "TERMS_LINK": "Conditions générales", + "AND": "et la", + "PRIVACY_LINK": "Politique de confidentialité", + "REQUIRED_ERROR": "Pour continuer vous devez accepter les Conditions et la Confidentialité.", + "UPLOAD_NOTICE_PREFIX": "En téléversant un fichier vous acceptez notre", + "UPLOAD_NOTICE_LINK": "Politique de confidentialité" + }, + "PRIVACY": { + "META": { + "CONTROLLER": "Responsables du traitement : Matteo Caletti et Joe Kung (3D-Fab.ch).", + "CONTACT": "Contact confidentialité : info@3d-fab.ch" + }, + "S1": { + "TITLE": "1. Quelles données nous traitons", + "P1": "1.1. Nous collectons les données nécessaires aux devis et aux commandes : prénom, nom, e-mail, téléphone, adresse, données de livraison/facturation et détails de la commande.", + "P2": "1.2. Lorsque vous téléversez des fichiers 3D ou des pièces jointes techniques, les fichiers sont traités uniquement pour l'analyse, la production, l'assistance et la gestion de la commande." + }, + "S2": { + "TITLE": "2. Finalité du traitement", + "P1": "2.1. Nous utilisons les données exclusivement pour : préparer les devis, confirmer les commandes, recevoir les paiements, organiser les expéditions et fournir l'assistance après-vente.", + "P2": "2.2. Nous n'utilisons pas les données pour le profilage, le marketing automatisé ou la vente à des tiers." + }, + "S3": { + "TITLE": "3. Conservation des fichiers et des données", + "P1": "3.1. Les fichiers téléversés uniquement pour un devis sont conservés pendant la durée de la session et supprimés automatiquement à son expiration.", + "P2": "3.2. Les fichiers et données liés aux commandes confirmées sont conservés le temps nécessaire à la production, la livraison, l'assistance et les obligations administratives/légales, puis supprimés ou minimisés.", + "P3": "3.3. Les fichiers téléversés dans le calculateur sont utilisés uniquement pour l'analyse technique et l'estimation du devis et restent associés exclusivement à la session du calculateur." + }, + "S4": { + "TITLE": "4. Cookies et traçage", + "P1": "4.1. Nous n'utilisons pas de cookies de profilage, de marketing ou de traçage de tiers.", + "P2": "4.2. Nous n'utilisons pas de systèmes de tracking publicitaire. Les éventuelles données techniques temporaires sont utilisées uniquement pour le fonctionnement de la session." + }, + "S5": { + "TITLE": "5. Partage des données", + "P1": "5.1. Nous partageons les données uniquement avec des fournisseurs strictement nécessaires au service (hébergement, paiements, expéditions), en nous limitant aux informations indispensables.", + "P2": "5.2. Les fournisseurs traitent les données selon des instructions contractuelles et des mesures de sécurité appropriées." + }, + "S6": { + "TITLE": "6. Droits de l'utilisateur", + "P1": "6.1. Vous pouvez demander l'accès, la rectification, la suppression ou la limitation du traitement de vos données, dans les limites prévues par la loi.", + "P2": "6.2. Pour toute demande liée à la confidentialité, écrivez à info@3d-fab.ch. La version italienne de cette politique de confidentialité est la seule version juridiquement contraignante, sauf accord écrit contraire." + } + }, + "TERMS": { + "META": { + "PROVIDER": "Fournisseur : 3D-Fab.ch (Matteo Caletti et Joe Kung)", + "VERSION": "Version : v1.0", + "SCOPE": "Valables pour l'impression 3D FDM/FFF et les services associés, avec vente et livraison exclusivement en Suisse (CH)." + }, + "S1": { + "TITLE": "1. Données du fournisseur et contacts", + "P1": "1.1. Fournisseur : Matteo Caletti et Joe Kung.", + "P2": "1.2. Adresse : Lyss-strasse 71, Nidau 2560, CH.", + "P3": "1.3. E-mail : info@3d-fab.ch." + }, + "S2": { + "TITLE": "2. Champ d'application", + "P1": "2.1. Les présentes Conditions générales régissent l'impression 3D à la demande, les services accessoires (conseil technique, CAD, vérification de fichiers, post-traitement) et les éventuels articles standard.", + "P2": "2.2. Le fournisseur vend et livre exclusivement en Suisse (CH).", + "P3": "2.3. Elles s'appliquent aux commandes effectuées via site, e-mail ou autres canaux convenus ; des conditions différentes du client ne valent que si elles sont acceptées par écrit." + }, + "S3": { + "TITLE": "3. Définitions", + "P1": "3.1. Client : personne physique ou morale acheteuse. Fichiers du client : modèles 3D et données techniques fournis. Produit personnalisé : pièce réalisée selon les spécifications du client. Commande : demande acceptée par le fournisseur." + }, + "S4": { + "TITLE": "4. Conclusion du contrat et commande", + "P1": "4.1. Le contrat est conclu avec la confirmation de commande (e-mail/portail) ou avec le démarrage de la production après paiement/acompte.", + "P2": "4.2. Les devis automatiques peuvent être confirmés ou mis à jour après vérification technique minimale (imprimabilité, supports, limites machine).", + "P3": "4.3. Le fournisseur peut refuser des commandes techniquement non réalisables ou non conformes aux présentes conditions." + }, + "S5": { + "TITLE": "5. Prix, taxes et expédition", + "P1": "5.1. Les prix sont en CHF, sauf indication contraire concernant TVA incluse/exclue.", + "P2": "5.2. L'expédition et l'emballage sont indiqués séparément lorsque applicables.", + "P3": "5.3. Pour petites séries ou CAD complexe, des offres écrites avec conditions spécifiques peuvent être appliquées (échantillons, paliers, approbation première pièce)." + }, + "S6": { + "TITLE": "6. Paiements", + "P1": "6.1. Méthodes acceptées : TWINT et virement bancaire.", + "P2": "6.2. Sauf accord contraire, la production démarre seulement après paiement.", + "P3": "6.3. Pour le conseil CAD et les petites séries, un acompte (30-100%) et/ou le solde avant livraison peut être demandé.", + "P4": "6.4. Coordonnées bancaires : Joe Kung, IBAN CH74 0900 0000 1548 2158 1, Via G. Pioda 29a, 6710 Biasca." + }, + "S7": { + "TITLE": "7. Fichiers du client et responsabilité technique", + "P1": "7.1. Le client garantit disposer des droits sur les fichiers et que leur usage ne viole pas des droits de tiers (copyright, brevets, licences, secrets industriels).", + "P2": "7.2. Le client est responsable de la conformité du modèle, du choix du matériau, de l'adéquation à l'usage final et du respect des normes applicables.", + "P3": "7.3. Le fournisseur peut suggérer des modifications pour améliorer imprimabilité et résultat, mais n'exerce pas une fonction de certification du produit final sauf accord écrit." + }, + "S8": { + "TITLE": "8. Qualité FDM/FFF et tolérances", + "P1": "8.1. L'impression FDM/FFF comporte des caractéristiques intrinsèques : lignes de couche, anisotropie mécanique, micro-imperfections, variations de couleur et possibles retraits/déformations liés à la géométrie et au matériau.", + "P2": "8.2. Tolérances standard (sauf accord écrit) : jusqu'à 100 mm +/-0.3 mm ; au-delà de 100 mm +/-0.5% (minimum +/-0.3 mm).", + "P3": "8.3. Les exigences esthétiques ou dimensionnelles critiques doivent être convenues avant la commande (ex. échantillon, mesures de contrôle, finition spécifique)." + }, + "S9": { + "TITLE": "9. Post-traitement et travaux additionnels", + "P1": "9.1. Des travaux comme retrait des supports, ponçage, primaire/peinture ou inserts filetés sont réalisés seulement si convenus et peuvent introduire des variations dimensionnelles ou esthétiques.", + "P2": "9.2. Sur demande, une approbation de la première pièce ou d'un échantillon peut être prévue, éventuellement payante." + }, + "S10": { + "TITLE": "10. Délais de production et de livraison", + "P1": "10.1. Les délais indiqués sont des estimations basées sur charge de travail, complexité et disponibilité des matériaux.", + "P2": "10.2. Les retards dus à des causes externes (transporteurs, fournisseurs, pannes, force majeure) ne donnent pas automatiquement droit à des pénalités sauf accord écrit.", + "P3": "10.3. Le client doit fournir des adresses correctes et complètes ; les éventuels coûts de relivraison pour adresse erronée restent à la charge du client." + }, + "S11": { + "TITLE": "11. Droit de rétractation et annulation", + "P1": "11.1. Sauf exceptions confirmées par écrit, aucun droit de rétractation ou de retour n'est prévu après la commande.", + "P2": "11.2. Les produits personnalisés ne sont pas annulables ni remboursables après démarrage de la production.", + "P3": "11.3. Le fournisseur peut accepter des exceptions avant démarrage de la production, en retenant les éventuels coûts déjà engagés.", + "P4": "11.4. Toute condition spéciale doit figurer dans l'offre, la confirmation de commande ou des communications écrites." + }, + "S12": { + "TITLE": "12. Réclamations, défauts et recours", + "P1": "12.1. Le client doit contrôler les produits à la livraison et signaler d'éventuels défauts sous 7 jours, par écrit, avec photo/vidéo et description.", + "P2": "12.2. Les signes typiques FDM, petites variations chromatiques, imperfections non fonctionnelles ou tolérances dans les limites convenues ne constituent pas automatiquement un défaut.", + "P3": "12.3. En cas de défaut imputable au fournisseur, les recours sont au choix du fournisseur : réimpression/remplacement ou remboursement limité à la valeur de la pièce ou de la commande défectueuse.", + "P4": "12.4. Avant réimpression ou remboursement, la restitution de la pièce peut être demandée ; si le défaut est confirmé, le retour est à la charge du fournisseur." + }, + "S13": { + "TITLE": "13. Usages interdits et conformité", + "P1": "13.1. Le fournisseur peut refuser des commandes relatives à des objets illégaux, armes ou pièces réglementées, applications critiques pour la sécurité ou médicales sans accords et validations dédiés.", + "P2": "13.2. Le client reste responsable de l'usage final et de la conformité réglementaire du produit." + }, + "S14": { + "TITLE": "14. Propriété intellectuelle et licences", + "P1": "14.1. Les droits sur les fichiers du client restent au client ou aux titulaires concernés. Le client concède au fournisseur une licence limitée à l'usage pour l'évaluation technique et la production.", + "P2": "14.2. Sauf accord contraire, les fichiers et projets CAD développés par le fournisseur sont livrés après paiement, avec droit d'usage pour les objectifs convenus.", + "P3": "14.3. Le client dégage le fournisseur de toute réclamation de tiers liée à des fichiers ou instructions fournis par le client." + }, + "S15": { + "TITLE": "15. Protection des données", + "P1": "15.1. Le fournisseur traite les données personnelles pour la gestion des commandes, paiements, expéditions et assistance.", + "P2": "15.2. Les données peuvent être partagées avec des fournisseurs techniques et transporteurs uniquement dans la mesure nécessaire à la fourniture du service." + }, + "S16": { + "TITLE": "16. Limitation de responsabilité", + "P1": "16.1. Dans les limites légales, le fournisseur répond seulement des dommages directs prévisibles et, en tout cas, pas au-delà de la valeur de la commande relative au produit ou service contesté.", + "P2": "16.2. Sont exclus, dans les limites autorisées, les dommages indirects, perte de profit, interruption d'activité, perte de données et dommages consécutifs.", + "P3": "16.3. Restent réservées les responsabilités non excluables par la loi (ex. dol ou faute grave)." + }, + "S17": { + "TITLE": "17. Force majeure", + "P1": "17.1. Des événements hors du contrôle raisonnable du fournisseur (pannes, coupures, retards fournisseurs, grèves, mesures d'autorité) peuvent provoquer des prorogations ou suspensions sans responsabilité." + }, + "S18": { + "TITLE": "18. Droit applicable et juridiction compétente", + "P1": "18.1. Le droit suisse s'applique.", + "P2": "18.2. Juridiction compétente : siège du fournisseur, sauf normes impératives de protection des consommateurs.", + "P3": "18.3. En cas de divergences d'interprétation, la version italienne des présentes conditions prévaut et constitue la seule version juridiquement contraignante, sauf accord écrit contraire." + } + } + }, + "CONTACT": { + "TITLE": "Contactez-nous", + "SEND": "Envoyer le message", + "REQ_TYPE_LABEL": "Type de demande", + "TYPE_PRIVATE": "Privé", + "TYPE_COMPANY": "Entreprise", + "REQ_TYPE_CUSTOM": "Devis personnalisé", + "REQ_TYPE_SERIES": "Impression en série", + "REQ_TYPE_CONSULT": "Consultation", + "REQ_TYPE_QUESTION": "Questions générales", + "PHONE": "Téléphone", + "IS_COMPANY": "Êtes-vous une entreprise ?", + "COMPANY_NAME": "Raison sociale", + "REF_PERSON": "Personne de référence", + "UPLOAD_LABEL": "Pièces jointes", + "UPLOAD_HINT": "Max 15 fichiers. Pris en charge : images, vidéos, PDF, documents Office, STL/STEP/3MF/OBJ/IGES, DWG/DXF. Fichiers compressés non autorisés.", + "DROP_FILES": "Déposez les fichiers ici ou cliquez pour téléverser", + "PLACEHOLDER_NAME": "Votre nom", + "PLACEHOLDER_EMAIL": "votre@email.com", + "PLACEHOLDER_PHONE": "+41 00 000 00 00", + "PLACEHOLDER_COMPANY": "Nom de l'entreprise", + "PLACEHOLDER_REF_PERSON": "Personne de référence", + "LABEL_MESSAGE": "Message *", + "LABEL_EMAIL": "E-mail *", + "LABEL_NAME": "Nom *", + "MSG_SENT": "Envoyé !", + "ERR_MAX_FILES": "Limite maximale de 15 fichiers atteinte.", + "ERR_COMPRESSED_FILES": "Les fichiers compressés ne sont pas autorisés (ZIP/RAR/7z/TAR/GZ).", + "SUCCESS_TITLE": "Message envoyé avec succès", + "SUCCESS_DESC": "Merci de nous avoir contactés. Nous avons reçu votre message et vous enverrons un e-mail récapitulatif prochainement.", + "SEND_ANOTHER": "Envoyer un autre message", + "HERO_SUBTITLE": "Nous sommes là pour vous aider. Remplissez le formulaire ci-dessous pour toute demande.", + "FILE_TYPE_PDF": "PDF", + "FILE_TYPE_3D": "3D", + "FILE_TYPE_VIDEO": "Vidéo", + "FILE_TYPE_DOC": "DOC", + "FILE_TYPE_FILE": "FICHIER", + "ERROR_SUBMIT": "Erreur lors de l'envoi de la demande. Réessayez.", + "REMOVE_FILE": "Supprimer le fichier joint" + }, + "CHECKOUT": { + "TITLE": "Checkout", + "SUBTITLE": "Complétez votre commande en saisissant les détails de livraison et de paiement.", + "CONTACT_INFO": "Informations de contact", + "BILLING_ADDR": "Adresse de facturation", + "SHIPPING_ADDR": "Adresse de livraison", + "FIRST_NAME": "Prénom", + "LAST_NAME": "Nom", + "EMAIL": "E-mail", + "PHONE": "Téléphone", + "COMPANY_NAME": "Nom de l'entreprise", + "ADDRESS_1": "Adresse (Rue et numéro)", + "ADDRESS_2": "Informations supplémentaires (optionnel)", + "ZIP": "Code postal", + "CITY": "Ville", + "COUNTRY": "Pays", + "SHIPPING_SAME": "L'adresse de livraison est la même que l'adresse de facturation", + "PLACE_ORDER": "Envoyer la commande", + "PROCESSING": "Traitement...", + "SUMMARY_TITLE": "Récapitulatif de la commande", + "SUBTOTAL": "Sous-total", + "ITEMS_BASE_SUBTOTAL": "Sous-total de base des articles", + "MACHINE_COST": "Coût machine", + "SETUP_FEE": "Coût de setup", + "TOTAL": "Total", + "QTY": "Qté", + "PER_PIECE": "par pièce", + "SHIPPING": "Expédition (CH)", + "INVALID_EMAIL": "E-mail invalide", + "COMPANY_OPTIONAL": "Nom de l'entreprise (Optionnel)", + "REF_PERSON_OPTIONAL": "Personne de référence (Optionnel)", + "SHIPPING_CALCULATED_NEXT_STEP": "le coût d'expédition est calculé à l'étape suivante", + "EXCLUDES_SHIPPING": "Coût d'expédition exclu", + "ERR_NO_SESSION_START": "Aucune session active trouvée. Commencez un nouveau devis.", + "ERR_LOAD_SESSION": "Impossible de charger les détails de la session. Réessayez.", + "ERR_NO_SESSION_CREATE_ORDER": "Aucune session active trouvée. Impossible de créer la commande.", + "ERR_CREATE_ORDER": "Impossible de créer la commande. Réessayez." + }, + "PAYMENT": { + "TITLE": "Paiement", + "METHOD": "Méthode de paiement", + "TWINT_TITLE": "Payer avec TWINT", + "TWINT_DESC": "Scannez le code avec l'application TWINT, sur mobile cliquez sur le bouton.", + "TWINT_OPEN": "Ouvrir directement dans TWINT", + "TWINT_LINK": "Ouvrir le lien de paiement", + "BANK_TITLE": "Virement bancaire", + "BANK_OWNER": "Titulaire", + "BANK_IBAN": "IBAN", + "BANK_REF": "Référence", + "BILLING_INFO_HINT": "Nous avons rempli les champs pour vous, merci de ne pas modifier le motif de paiement", + "DOWNLOAD_QR": "Télécharger la facture QR (PDF)", + "DOWNLOAD_CONFIRMATION": "Télécharger la confirmation (PDF)", + "CONFIRM": "J'ai effectué le paiement", + "SUMMARY_TITLE": "Récapitulatif de la commande", + "SUBTOTAL": "Sous-total", + "SHIPPING": "Expédition", + "SETUP_FEE": "Coût de setup", + "TOTAL": "Total", + "LOADING": "Chargement des détails de la commande...", + "METHOD_TWINT": "TWINT", + "METHOD_BANK": "Facture QR / Virement", + "STATUS_REPORTED_TITLE": "Commande en cours", + "STATUS_REPORTED_DESC": "Nous avons enregistré votre opération. Dès que nous confirmons le paiement, la commande entrera en production.", + "IN_VERIFICATION": "Paiement signalé", + "TWINT_QR_ALT": "QR de paiement TWINT", + "TWINT_BUTTON_ALT": "Bouton TWINT intégré" + }, + "TRACKING": { + "TITLE": "Statut de la commande", + "SUBTITLE": "Consultez le statut de votre commande et gérez le paiement si nécessaire.", + "STEP_PENDING": "En attente", + "STEP_REPORTED": "En vérification", + "STEP_PRODUCTION": "En production", + "STEP_SHIPPED": "Expédié" + }, + "ORDER_CONFIRMED": { + "TITLE": "Commande confirmée", + "SUBTITLE": "Paiement enregistré. Votre commande est maintenant en traitement.", + "STATUS": "En traitement", + "HEADING": "Nous préparons votre commande", + "ORDER_REF": "Référence commande", + "PROCESSING_TEXT": "Dès que nous confirmons le paiement, votre commande passera en production.", + "EMAIL_TEXT": "Nous vous enverrons un e-mail avec mise à jour du statut et prochaines étapes.", + "BACK_HOME": "Retour à l'accueil" + }, + "STL_VIEWER": { + "LOADING": "Chargement du modèle 3D..." + }, + "ORDER": { + "ERR_ID_NOT_FOUND": "ID de commande introuvable.", + "ERR_LOAD_ORDER": "Impossible de charger les détails de la commande.", + "ERR_REPORT_PAYMENT": "Impossible de signaler le paiement. Réessayez.", + "NOT_AVAILABLE": "N/D" + }, + "DROPZONE": { + "DEFAULT_LABEL": "Glissez les fichiers ici ou cliquez pour téléverser", + "DEFAULT_SUBTEXT": "Prend en charge .STL, .3MF, .STEP" + }, + "COLOR": { + "AVAILABLE_COLORS": "Couleurs disponibles", + "CATEGORY_GLOSSY": "Brillants", + "CATEGORY_MATTE": "Mats", + "NAME": { + "BLACK": "Noir", + "WHITE": "Blanc", + "RED": "Rouge", + "BLUE": "Bleu", + "GREEN": "Vert", + "YELLOW": "Jaune", + "MATTE_BLACK": "Noir mat", + "MATTE_WHITE": "Blanc mat", + "MATTE_GRAY": "Gris mat" + } + } +} diff --git a/frontend/src/assets/i18n/it.json b/frontend/src/assets/i18n/it.json index e2f781e..5e89136 100644 --- a/frontend/src/assets/i18n/it.json +++ b/frontend/src/assets/i18n/it.json @@ -4,7 +4,8 @@ "CALCULATOR": "Calcolatore", "SHOP": "Shop", "ABOUT": "Chi Siamo", - "CONTACT": "Contattaci" + "CONTACT": "Contattaci", + "LANGUAGE_SELECTOR": "Selettore lingua" }, "FOOTER": { "PRIVACY": "Privacy",