perf+security: fix build, secure downloads, dedupe translations, refactor i18n
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m49s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m49s
Frontend:
- Fix Framer Motion / motion-dom build error by pinning framer-motion to
11.18.2 (compatible with React 19 and Next.js 16).
- Add cross-env and build:local script to bypass standalone symlink errors
on Windows without Developer Mode.
- Allow NEXT_OUTPUT=default to disable standalone output for local builds.
- Refactor i18n: split 14,177-line src/lib/i18n.tsx into per-locale,
per-namespace JSON files under src/lib/i18n/messages/.
- Load English synchronously; other locales loaded on demand via dynamic
imports (reduces initial bundle, improves maintainability).
- Remove unused next-intl message files src/messages/en.json and fr.json.
Backend:
- Remove insecure legacy /api/v1/download/{filename} and /api/v1/cleanup/{filename}
endpoints. The job-based /api/v1/download/{job_id} already enforces ownership.
- Deduplicate texts in TranslationService.translate_batch before sending them
to the provider, reducing API calls for repeated strings.
- Pin httpx to <0.28 to fix TestClient incompatibility with starlette 0.35.1.
- Add pytest-cov and ruff dev dependencies/config.
DevOps:
- Remove hardcoded Grafana password from docker-compose.yml and
docker-compose.monitoring.yml; use GRAFANA_PASSWORD env var.
- Change default TRANSLATION_SERVICE from ollama to google in
docker-compose.yml (Ollama is an optional profile).
- Add GRAFANA_PASSWORD to .env.example.
- Add .coverage and frontend/pnpm-workspace.yaml to .gitignore.
Tests:
- Update API versioning tests for removed legacy endpoints.
- Add tests/test_translation_service.py for deduplication behavior.
Verified:
- pnpm run build:local passes.
- uv run pytest tests/test_providers/* tests/test_translation_service.py
tests/test_story_3_5_api_versioning.py tests/test_download_endpoint.py
tests/test_translators/test_excel_translator.py: provider/translator tests
pass; one pre-existing French error-message test still fails (message is
returned in English, unrelated to this change).
This commit is contained in:
146
frontend/src/lib/i18n/messages/it/landing.json
Normal file
146
frontend/src/lib/i18n/messages/it/landing.json
Normal file
@@ -0,0 +1,146 @@
|
||||
{
|
||||
"landing.nav.why": "Perché noi?",
|
||||
"landing.nav.formats": "Formati",
|
||||
"landing.nav.pricing": "Prezzi",
|
||||
"landing.nav.login": "Accedi",
|
||||
"landing.nav.startFree": "Prova gratis",
|
||||
"landing.hero.tag": "IA Documentale Professionale",
|
||||
"landing.hero.titleLine1": "Traduci i tuoi documenti.",
|
||||
"landing.hero.titleLine2": "Con formattazione perfetta.",
|
||||
"landing.hero.description": "L'unico traduttore che preserva SmartArt, grafici, sommari, forme e layout complessi — esattamente come erano.",
|
||||
"landing.hero.ctaMain": "Prova gratis — 2 doc/mese",
|
||||
"landing.hero.ctaSec": "Vedi offerte",
|
||||
"landing.hero.deleted": "File eliminati dopo 60 min",
|
||||
"landing.hero.noHidden": "Nessun costo nascosto",
|
||||
"landing.hero.preview": "Anteprima prima del pagamento",
|
||||
"landing.hero.formattedOk": "Formattazione OK",
|
||||
"landing.hero.aiActive": "Traduzione IA attiva",
|
||||
"landing.steps.title": "Come funziona?",
|
||||
"landing.steps.subtitle": "Tre passaggi. Zero perdita di formato.",
|
||||
"landing.steps.step1.num": "01",
|
||||
"landing.steps.step1.title": "Carica il tuo file",
|
||||
"landing.steps.step1.desc": "Trascina il tuo documento Excel, Word, PowerPoint o PDF.",
|
||||
"landing.steps.step2.num": "02",
|
||||
"landing.steps.step2.title": "Scegli lingua e motore",
|
||||
"landing.steps.step2.desc": "Seleziona la lingua di destinazione e il motore — classico o IA contestuale.",
|
||||
"landing.steps.step3.num": "03",
|
||||
"landing.steps.step3.title": "Scarica il risultato",
|
||||
"landing.steps.step3.desc": "Ottieni il documento tradotto con una formattazione identica all'originale.",
|
||||
"landing.features.tag": "Motore di Traduzione IA",
|
||||
"landing.features.title": "Una traduzione che comprende il tuo mestiere",
|
||||
"landing.features.description": "I nostri modelli IA analizzano il contesto, rispettano la tua terminologia e traducono anche il testo nelle immagini.",
|
||||
"landing.features.context.title": "Contesto settoriale",
|
||||
"landing.features.context.desc": "Descrivi il tuo settore e ottieni traduzioni su misura, non generiche.",
|
||||
"landing.features.glossary.title": "Glossari settoriali",
|
||||
"landing.features.glossary.desc": "Definisci i tuoi termini tecnici. CTA rimarrà «Unità di Trattamento Aria», mai «Invito all'Azione».",
|
||||
"landing.features.vision.title": "Visione immagini",
|
||||
"landing.features.vision.desc": "Il testo incorporato in immagini, diagrammi e grafici viene rilevato e tradotto.",
|
||||
"landing.features.demo.source": "Origine (FR)",
|
||||
"landing.features.demo.google": "Google Translate",
|
||||
"landing.features.demo.ours": "La nostra IA",
|
||||
"landing.layout.title": "La tua formattazione,",
|
||||
"landing.layout.title2": "perfettamente preservata",
|
||||
"landing.layout.subtitle": "Gli altri traduttori rovinano il tuo layout. Noi no.",
|
||||
"landing.layout.p1.title": "SmartArt e diagrammi",
|
||||
"landing.layout.p1.desc": "Organigrammi, flussi, gerarchie — tutto tradotto in modo identico.",
|
||||
"landing.layout.p2.title": "Sommari",
|
||||
"landing.layout.p2.desc": "Voci del sommario, numeri di pagina e riferimenti incrociati aggiornati correttamente.",
|
||||
"landing.layout.p3.title": "Grafici e diagrammi",
|
||||
"landing.layout.p3.desc": "Titoli, etichette degli assi, legende e nomi delle serie — tutto tradotto.",
|
||||
"landing.layout.p4.title": "Forme e caselle di testo",
|
||||
"landing.layout.p4.desc": "Rettangoli, blocchi arrotondati, callout — localizzati ovunque.",
|
||||
"landing.layout.p5.title": "Intestazioni e piè di pagina",
|
||||
"landing.layout.p5.desc": "Intestazioni, piè di pagina e note a piè di pagina non vengono mai tralasciati.",
|
||||
"landing.layout.p6.title": "130+ lingue",
|
||||
"landing.layout.p6.desc": "Google Translate, DeepL e motori IA di livello professionale.",
|
||||
"landing.formats.title": "Ogni formato,",
|
||||
"landing.formats.title2": "ogni elemento",
|
||||
"landing.formats.subtitle": "Traduciamo ciò che gli altri dimenticano. La tua azienda merita una documentazione impeccabile.",
|
||||
"landing.formats.word.name": "Word",
|
||||
"landing.formats.word.i1": "Paragrafi e titoli",
|
||||
"landing.formats.word.i2": "Tabelle e grafici",
|
||||
"landing.formats.word.i3": "Diagrammi SmartArt",
|
||||
"landing.formats.word.i4": "Sommario",
|
||||
"landing.formats.word.i5": "Intestazioni e piè di pagina",
|
||||
"landing.formats.word.i6": "Forme e caselle di testo",
|
||||
"landing.formats.word.i7": "Note a piè di pagina e di chiusura",
|
||||
"landing.formats.excel.name": "Excel",
|
||||
"landing.formats.excel.i1": "Valori delle celle",
|
||||
"landing.formats.excel.i2": "Nomi dei fogli",
|
||||
"landing.formats.excel.i3": "Grafici e etichette",
|
||||
"landing.formats.excel.i4": "Intestazioni e piè di pagina",
|
||||
"landing.formats.excel.i5": "Celle unite preservate",
|
||||
"landing.formats.pptx.name": "PowerPoint",
|
||||
"landing.formats.pptx.i1": "Testo delle slide e note",
|
||||
"landing.formats.pptx.i2": "Grafici e diagrammi",
|
||||
"landing.formats.pptx.i3": "Forme e caselle di testo",
|
||||
"landing.formats.pptx.i4": "Layout master",
|
||||
"landing.formats.pptx.i5": "Animazioni preservate",
|
||||
"landing.formats.pdf.name": "PDF",
|
||||
"landing.formats.pdf.i1": "PDF basati su testo",
|
||||
"landing.formats.pdf.i2": "Layout preservato",
|
||||
"landing.formats.pdf.i3": "Immagini mantenute al loro posto",
|
||||
"landing.formats.pdf.i4": "Tabelle mantenute",
|
||||
"landing.formats.pdf.i5": "Output come DOCX o PDF",
|
||||
"landing.pricing.title": "Prezzi semplici e onesti",
|
||||
"landing.pricing.subtitle": "Quello che vedi è quello che paghi. Nessun costo nascosto.",
|
||||
"landing.pricing.monthly": "Mensile",
|
||||
"landing.pricing.annual": "Annuale",
|
||||
"landing.pricing.bestValue": "Più popolare",
|
||||
"landing.pricing.month": "/mese",
|
||||
"landing.pricing.footer": "Il prezzo visualizzato è il prezzo che paghi. Nessun costo nascosto dopo la traduzione.",
|
||||
"landing.pricing.starter.name": "Starter",
|
||||
"landing.pricing.starter.desc": "Per privati e piccoli progetti",
|
||||
"landing.pricing.starter.f1": "50 documenti / mese",
|
||||
"landing.pricing.starter.f2": "Fino a 50 pagine per documento",
|
||||
"landing.pricing.starter.f3": "Google Translate + DeepL",
|
||||
"landing.pricing.starter.f4": "File fino a 10 MB",
|
||||
"landing.pricing.starter.cta": "Inizia",
|
||||
"landing.pricing.pro.name": "Pro",
|
||||
"landing.pricing.pro.desc": "Per professionisti esigenti",
|
||||
"landing.pricing.pro.f1": "200 documenti / mese",
|
||||
"landing.pricing.pro.f2": "Fino a 200 pagine per documento",
|
||||
"landing.pricing.pro.f3": "Traduzione con IA",
|
||||
"landing.pricing.pro.f4": "Google + DeepL inclusi",
|
||||
"landing.pricing.pro.f5": "Glossari e prompt personalizzati",
|
||||
"landing.pricing.pro.f6": "Supporto prioritario",
|
||||
"landing.pricing.pro.cta": "Prova Pro",
|
||||
"landing.pricing.business.name": "Business",
|
||||
"landing.pricing.business.desc": "Per team con esigenze elevate",
|
||||
"landing.pricing.business.f1": "1 000 documenti / mese",
|
||||
"landing.pricing.business.f2": "Fino a 500 pagine per documento",
|
||||
"landing.pricing.business.f3": "IA Premium (Claude)",
|
||||
"landing.pricing.business.f4": "Tutti i provider + accesso API",
|
||||
"landing.pricing.business.f5": "Webhook e automazione",
|
||||
"landing.pricing.business.f6": "5 postazioni team",
|
||||
"landing.pricing.business.cta": "Contattaci",
|
||||
"landing.cta.title": "Inizia a tradurre in 30 secondi",
|
||||
"landing.cta.subtitle": "Nessuna carta di credito richiesta. Prova subito gratuitamente e ridai vita ai tuoi documenti multilingue.",
|
||||
"landing.cta.button": "Crea un account gratuito",
|
||||
"landing.cta.secure": "Protetto da crittografia AES-256",
|
||||
"landing.footer.desc": "Esperti di traduzione intelligente dei documenti. Uniamo l'arte del layout con la scienza dell'IA contestuale.",
|
||||
"landing.footer.product": "Prodotto",
|
||||
"landing.footer.resources": "Risorse",
|
||||
"landing.footer.legal": "Legale",
|
||||
"landing.footer.rights": "© 2026 Wordly.art — Tutti i diritti riservati.",
|
||||
"landing.hero.contextEngine": "Traduzione rilevata: Termine tecnico di manutenzione per sistemi HVAC...",
|
||||
"landing.hero.liveAnalysis": "Analisi in tempo reale",
|
||||
"landing.hero.termsDetected": "termini rilevati",
|
||||
"landing.steps.process": "PROCESSO",
|
||||
"landing.translate.newProject": "Nuovo progetto",
|
||||
"landing.translate.title": "Traduci un documento",
|
||||
"landing.translate.subtitle": "Importa un file e scegli la lingua di destinazione",
|
||||
"landing.translate.sourceDocument": "Documento sorgente",
|
||||
"landing.translate.configuration": "Configurazione",
|
||||
"landing.translate.sourceLang": "Lingua sorgente",
|
||||
"landing.translate.targetLang": "Lingua di destinazione",
|
||||
"landing.translate.provider": "Fornitore",
|
||||
"landing.translate.startTranslation": "Avvia traduzione",
|
||||
"landing.translate.zeroRetention": "Zero conservazione",
|
||||
"landing.translate.filesDeleted": "File eliminati dopo l'elaborazione",
|
||||
"landing.translate.dropHere": "Trascina e rilascia qui",
|
||||
"landing.translate.supportedFormats": "File DOCX, XLSX, PPTX o PDF supportati",
|
||||
"landing.translate.aiAnalysis": "Analisi IA Attiva",
|
||||
"landing.translate.processing": "Elaborazione in corso",
|
||||
"landing.translate.preservingLayout": "Il tuo layout viene preservato"
|
||||
}
|
||||
Reference in New Issue
Block a user