feat(translation): quality pipeline overhaul + new features (audit 2026-08-29)
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m20s

Translation quality & format preservation:
- Word: merge adjacent same-format runs into one unit (sentence-level
  coherence like inline-tag handling); translate comments/balloons;
  dedupe textbox collection (was translated twice); RTL no longer
  overrides center/justify alignment; CJK/Arabic font hints (eastAsia/cs)
- PPTX: chart translations now actually reach the output file
  (ChartPart.blob is read-only — rewrite chart XML in the saved ZIP);
  CJK typeface hints (a:ea)
- Excel: sheet renames no longer break references — rewrite cell
  formulas (3D/quoted), defined names, data validations, cond. formats
- PDF: bold/italic honored (hebo/heit/hebi); table cells never merge;
  unchanged blocks left untouched (typography preserved, fixes duplicate
  hyperlinks); attempted/changed stats + route gate now cover PDF;
  CJK font paths; scanned PDFs via Mistral OCR (detection + admin settings)

Features:
- formality param (formal/informal) + automatic regional-variant prompts
- output_mode=bilingual docx (source above translation)
- per-user translation memory on Redis (falls back to LRU), context-hashed
- QA report + 0-100 confidence score in job status; L0 on by default
- OpenAI-compatible providers: whole chunk in ONE numbered-JSON request
  (~15x fewer calls) with per-item fallback; base prompt always present
  (custom prompt no longer replaces translation instructions)

Infra & marketing alignment:
- plan-based engine gating + vision gating (closes paid-engine leak);
  /providers/available filtered per plan; 107 languages exposed
- zh-CN/zh-TW validation fixed; libmagic disabled on Windows (native crash)
- admin: Mistral OCR settings + engine status dashboard; httpx<0.28 pin
  (TestClient breakage); Prometheus test fixture fixed
- marketing docs aligned with code (PDF+OCR, retention, engines, pricing)
- security: .env.ionos/.env.production/provider_settings.json removed

Tests: 1173 passed / 0 failed (6 network tests deselected: free Google
endpoint temporarily blocked from this machine)
This commit is contained in:
2026-08-29 18:38:09 +02:00
parent 992f13d53c
commit 526c87348f
87 changed files with 6996 additions and 1024 deletions

View File

@@ -0,0 +1,82 @@
"use client"
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
const FAQS = [
{
q: "Does Office Translator really keep the formatting intact?",
a: "Yes. Unlike generic translators that flatten your file into plain text, we translate in place: merged cells, formulas, fonts, borders, headers, footers, tables and slide layouts are preserved. You download a document that looks like it was written in the target language from the start.",
},
{
q: "Which file formats are supported?",
a: "Excel (.xlsx), Word (.docx), PowerPoint (.pptx) and PDF (.pdf). Scanned PDFs (image-only pages) are handled too — the text is recovered via OCR before translation. We also translate text embedded in images inside your documents using vision-capable models on Pro and Business plans.",
},
{
q: "Which translation engines can I use?",
a: "Up to seven providers depending on your plan: Google (free and fast), DeepL (best for business text), Google Cloud, and LLM engines (OpenRouter in eco & premium tiers — DeepSeek, Gemini, Claude —, OpenAI, Grok by xAI). On paid plans you pick the engine per document.",
},
{
q: "How are my documents handled? Is my data safe?",
a: "Files are processed on our servers and automatically deleted: uploads after 30 minutes, translated results within 2 hours (zero-retention mode). We never train models on your content, and documents are encrypted in transit (TLS 1.2+).",
},
{
q: "What is a glossary and why would I need one?",
a: "A glossary is a set of custom term pairs (e.g. a specific HVAC or legal term and its approved translation). The engine applies your terminology consistently across every document, which is essential for technical, legal and medical content.",
},
{
q: "What happens when I hit my monthly document limit?",
a: "Translation stops with a clear message and your usage is shown in the dashboard. You can upgrade your plan or buy extra credit packs (from €0.06 per page) without changing your subscription.",
},
{
q: "Can I integrate Office Translator into my own tools?",
a: "Yes. The Business plan includes API access with 10,000 calls per month and API keys with scoped permissions. Enterprise plans offer custom call volumes. The API mirrors the web workflow: submit a file, poll the job, download the result.",
},
{
q: "Can I cancel my subscription?",
a: "Anytime, from the dashboard or the Stripe billing portal. Your plan stays active until the end of the billing period, and you can download all your translated documents before that.",
},
{
q: "Is there a free trial of paid plans?",
a: "The Free plan already gives you 2 full documents per month with no card required, so you can validate quality on your own files before upgrading. Paid plans can be cancelled at any time.",
},
{
q: "Do you offer team or agency options?",
a: "The Business plan includes 5 team seats with shared usage. For larger teams, agencies and multi-country operations, our Enterprise plan provides custom seats, custom LLM routing and dedicated support.",
},
]
export function FaqSection() {
return (
<section id="faq" className="flex flex-col items-center gap-8 px-6 py-16 md:py-24">
<div className="flex flex-col items-center gap-3 text-center">
<h2 className="text-balance text-3xl font-bold tracking-tight text-foreground md:text-4xl">
Frequently asked questions
</h2>
<p className="max-w-xl text-pretty text-sm leading-relaxed text-muted-foreground md:text-base">
Everything you need to know about translating documents with zero
formatting loss.
</p>
</div>
<div className="w-full max-w-3xl">
<Accordion type="single" collapsible className="w-full">
{FAQS.map((faq, i) => (
<AccordionItem key={i} value={`faq-${i}`}>
<AccordionTrigger className="text-sm md:text-base">
{faq.q}
</AccordionTrigger>
<AccordionContent className="text-sm leading-relaxed text-muted-foreground">
{faq.a}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</div>
</section>
)
}