From 62a3f5702e68728a49f5639ee047d3f1f4d5c6e8 Mon Sep 17 00:00:00 2001 From: Adam Ridene Date: Sat, 18 Jul 2026 20:19:29 +0100 Subject: [PATCH 1/4] Translate landing page - all text now uses i18n (EN/FR/AR) --- web/src/i18n.jsx | 132 ++++++++++++++++++++++++++++++++++ web/src/pages/LandingPage.jsx | 130 ++++++++++++++++----------------- 2 files changed, 198 insertions(+), 64 deletions(-) diff --git a/web/src/i18n.jsx b/web/src/i18n.jsx index b77d7de..8fdb179 100644 --- a/web/src/i18n.jsx +++ b/web/src/i18n.jsx @@ -2,6 +2,50 @@ import { createContext, useContext, useState, useCallback } from "react"; const LOCALES = { en: { + "landing.badge": "Fault-to-Fix Engine", + "landing.hero_title_1": "From fault code", + "landing.hero_title_2": "to fixed.", + "landing.hero_desc": "TORQ autonomously diagnoses machine faults, generates trilingual work orders, and dispatches the right technician all in real time.", + "landing.cta_demo": "Live Demo", + "landing.cta_how": "How it works", + "landing.problems_headline": "The Hidden Cost of Legacy Downtime", + "landing.problem_1_title": "Hours lost to manual searches", + "landing.problem_1_desc": "Technicians waste hours digging though dusty, 500 page physical manuals or fragmented PDFs to translate a single PLC fault code.", + "landing.problem_2_title": "The tribal knowledge expiry", + "landing.problem_2_desc": "Critical maintenance workarounds live only in the heads of senior engineers. When they retire or exit the plant floor, operational wisdom is permanently lost.", + "landing.problem_3_title": "Trilingual friction", + "landing.problem_3_desc": "Mismatches between machine logs, manufacturer documentation, and technician field languages (English, French, Arabic) create costly communication bottlenecks.", + "landing.stat_diag_accuracy": "Diagnosis accuracy", + "landing.stat_avg_time": "Avg time to diagnose", + "landing.stat_faults_resolved": "Faults resolved", + "landing.stat_faster": "Faster than manual triage", + "landing.stat_data_leakage": "Data leakage", + "landing.pipeline_title": "How TORQ drives the repair", + "landing.pipeline_subtitle": "From fault event to resolved work order entirely automated.", + "landing.features_title": "Features", + "landing.features_subtitle": "Built for the factory floor. No frills. No latency.", + "landing.feature_1_title": "AI Diagnosis", + "landing.feature_1_desc": "Hybrid search across manuals and repair history pinpoints root causes in seconds, not hours.", + "landing.feature_2_title": "Trilingual Work Orders", + "landing.feature_2_desc": "Every work order auto-generates in English, French, and Arabic as a downloadable PDF.", + "landing.feature_3_title": "Smart Dispatch", + "landing.feature_3_desc": "Routes the right technician based on skill, location, and availability.", + "landing.feature_4_title": "Self Learning", + "landing.feature_4_desc": "Every fix enriches the knowledge base. The model gets smarter with each resolved fault.", + "landing.feature_5_title": "Works With Your Setup", + "landing.feature_5_desc": "Report faults from the dashboard, connect machines that send digital alerts, or bridge older equipment — no special hardware required.", + "landing.how_title": "How it works", + "landing.how_subtitle": "Three steps from alarm to resolution.", + "landing.step_1_title": "A fault comes in", + "landing.step_1_desc": "A technician reports it from the dashboard, a connected machine sends an alert, or a bridge picks it up from older controllers. TORQ starts immediately, no matter how the fault arrives.", + "landing.step_2_title": "AI diagnoses against manuals + history", + "landing.step_2_desc": "Hybrid search (dense + BM25 + reranker) retrieves relevant documentation. A reasoning LLM produces a grounded diagnosis with citations.", + "landing.step_3_title": "Supervisor approves → technician routed", + "landing.step_3_desc": "The trilingual work order lands in the dashboard queue. One click to approve. The technician is dispatched with full context.", + "landing.cta_title": "Ready to see it in action?", + "landing.cta_desc": "Launch the live dashboard to watch faults flow through the pipeline in real time.", + "landing.cta_launch": "Launch Dashboard", + "dashboard.title": "Supervisor dashboard", "dashboard.subtitle": "Approval queue and downtime metrics", "dashboard.total": "Total work orders", @@ -77,6 +121,50 @@ const LOCALES = { "dashboard.toast_simulated": "Fault simulated", }, fr: { + "landing.badge": "Moteur de diagnostic de pannes", + "landing.hero_title_1": "Du code d'erreur", + "landing.hero_title_2": "à la réparation.", + "landing.hero_desc": "TORQ diagnostique automatiquement les pannes, génère des ordres de travail trilingues et envoie le technicien compétent en temps réel.", + "landing.cta_demo": "Démo en direct", + "landing.cta_how": "Comment ça marche", + "landing.problems_headline": "Le coût caché des temps d'arrêt", + "landing.problem_1_title": "Des heures perdues en recherches manuelles", + "landing.problem_1_desc": "Les techniciens perdent des heures à fouiller des manuels poussiéreux de 500 pages ou des PDFs fragmentés pour traduire un seul code d'erreur.", + "landing.problem_2_title": "L'expiration du savoir tribal", + "landing.problem_2_desc": "Les solutions de maintenance critiques n'existent que dans la tête des ingénieurs seniors. Quand ils partent, ce savoir opérationnel est perdu définitivement.", + "landing.problem_3_title": "Friction trilingue", + "landing.problem_3_desc": "Les décalages entre journaux machine, documentation fabricant et langues de terrain (anglais, français, arabe) créent des goulots d'étranglement coûteux.", + "landing.stat_diag_accuracy": "Précision diagnostic", + "landing.stat_avg_time": "Temps moyen diagnostic", + "landing.stat_faults_resolved": "Pannes résolues", + "landing.stat_faster": "Plus rapide que manuel", + "landing.stat_data_leakage": "Fuite de données", + "landing.pipeline_title": "Comment TORQ pilote la réparation", + "landing.pipeline_subtitle": "De l'événement de panne à l'ordre de travail résolu — entièrement automatisé.", + "landing.features_title": "Fonctionnalités", + "landing.features_subtitle": "Conçu pour l'usine. Sans fioriture. Sans latence.", + "landing.feature_1_title": "Diagnostic IA", + "landing.feature_1_desc": "La recherche hybride dans les manuels et l'historique identifie les causes racines en secondes, pas en heures.", + "landing.feature_2_title": "Ordres de travail trilingues", + "landing.feature_2_desc": "Chaque ordre de travail est généré automatiquement en anglais, français et arabe en PDF téléchargeable.", + "landing.feature_3_title": "Répartition intelligente", + "landing.feature_3_desc": "Achemine le bon technicien selon ses compétences, sa position et sa disponibilité.", + "landing.feature_4_title": "Auto-apprentissage", + "landing.feature_4_desc": "Chaque réparation enrichit la base de connaissances. Le modèle devient plus performant à chaque panne résolue.", + "landing.feature_5_title": "S'adapte à votre installation", + "landing.feature_5_desc": "Signalez les pannes depuis le tableau de bord, connectez des machines qui envoient des alertes, ou reliez des équipements plus anciens — aucun matériel spécial requis.", + "landing.how_title": "Comment ça marche", + "landing.how_subtitle": "Trois étapes de l'alarme à la résolution.", + "landing.step_1_title": "Une panne arrive", + "landing.step_1_desc": "Un technicien la signale depuis le tableau de bord, une machine connectée envoie une alerte, ou une passerelle la récupère depuis des contrôleurs plus anciens. TORQ démarre immédiatement, peu importe comment la panne arrive.", + "landing.step_2_title": "L'IA diagnostique manuels + historique", + "landing.step_2_desc": "La recherche hybride (dense + BM25 + reclassement) trouve la documentation pertinente. Un LLM produit un diagnostic fondé avec des citations.", + "landing.step_3_title": "Le superviseur approuve → technicien envoyé", + "landing.step_3_desc": "L'ordre de travail trilingue apparaît dans la file d'attente. Un clic pour approuver. Le technicien est dépêché avec tout le contexte.", + "landing.cta_title": "Prêt à voir la démonstration ?", + "landing.cta_desc": "Lancez le tableau de bord en direct pour voir les pannes traverser le pipeline en temps réel.", + "landing.cta_launch": "Lancer le tableau de bord", + "dashboard.title": "Tableau de bord superviseur", "dashboard.subtitle": "File d'approbation et métriques de temps d'arrêt", "dashboard.total": "Total ordres de travail", @@ -152,6 +240,50 @@ const LOCALES = { "dashboard.toast_simulated": "Défaut simulé", }, ar: { + "landing.badge": "محرك تحويل الخلل إلى إصلاح", + "landing.hero_title_1": "من رمز الخلل", + "landing.hero_title_2": "إلى الإصلاح.", + "landing.hero_desc": "يقوم TORQ بتشخيص أعطال الآلات تلقائياً، وإنشاء أوامر عمل ثلاثية اللغات، وإرسال الفني المناسب في الوقت الفعلي.", + "landing.cta_demo": "عرض توضيحي", + "landing.cta_how": "كيف يعمل", + "landing.problems_headline": "التكلفة الخفية لتوقف الآلات القديمة", + "landing.problem_1_title": "ساعات ضائعة في البحث اليدوي", + "landing.problem_1_desc": "يضيع الفنيون ساعات في البحث خلال أدلة ورقية مغبرة مكونة من 500 صفحة أو ملفات PDF مجزأة لترجمة رمز خطأ واحد.", + "landing.problem_2_title": "انتهاء صلاحية المعرفة الحرفية", + "landing.problem_2_desc": "تعيش حلول الصيانة الحرجة فقط في عقول المهندسين الكبار. عندما يتقاعدون أو يغادرون، تُفقد الحكمة التشغيلية إلى الأبد.", + "landing.problem_3_title": "الاحتكاك ثلاثي اللغات", + "landing.problem_3_desc": "عدم التطابق بين سجلات الآلة ووثائق الشركة المصنعة ولغات الفنيين الميدانية (الإنجليزية، الفرنسية، العربية) يخلق اختناقات اتصال مكلفة.", + "landing.stat_diag_accuracy": "دقة التشخيص", + "landing.stat_avg_time": "متوسط وقت التشخيص", + "landing.stat_faults_resolved": "الأعطال التي تم حلها", + "landing.stat_faster": "أسرع من الفرز اليدوي", + "landing.stat_data_leakage": "تسرب البيانات", + "landing.pipeline_title": "كيف يقود TORQ عملية الإصلاح", + "landing.pipeline_subtitle": "من حدث العطل إلى أمر العمل المُنجز — بشكل آلي بالكامل.", + "landing.features_title": "الميزات", + "landing.features_subtitle": "مُصمم لأرض المصنع. بدون زوائد. بدون تأخير.", + "landing.feature_1_title": "تشخيص بالذكاء الاصطناعي", + "landing.feature_1_desc": "البحث الهجين في الأدلة وسجل الإصلاحات يحدد الأسباب الجذرية في ثوانٍ، وليس ساعات.", + "landing.feature_2_title": "أوامر عمل ثلاثية اللغات", + "landing.feature_2_desc": "يتم إنشاء كل أمر عمل تلقائياً باللغات الإنجليزية والفرنسية والعربية بصيغة PDF قابلة للتحميل.", + "landing.feature_3_title": "توزيع ذكي", + "landing.feature_3_desc": "يوجه الفني المناسب بناءً على المهارة والموقع والتوفر.", + "landing.feature_4_title": "تعلم ذاتي", + "landing.feature_4_desc": "كل إصلاح يثري قاعدة المعرفة. يصبح النموذج أكثر ذكاءً مع كل عطل يتم حله.", + "landing.feature_5_title": "يتوافق مع إعداداتك", + "landing.feature_5_desc": "أبلغ عن الأعطال من لوحة التحكم، أو وصل آلات متصلة ترسل تنبيهات رقمية، أو اربط معدات أقدم — بدون أي متطلبات أجهزة خاصة.", + "landing.how_title": "كيف يعمل", + "landing.how_subtitle": "ثلاث خطوات من الإنذار إلى الحل.", + "landing.step_1_title": "يصل العطل", + "landing.step_1_desc": "يقوم فني بالإبلاغ عنه من لوحة التحكم، أو ترسل آلة متصلة تنبيهاً، أو تلتقطه بوابة من وحدات تحكم أقدم. يبدأ TORQ فوراً، بغض النظر عن كيفية وصول العطل.", + "landing.step_2_title": "التشخيص بالذكاء الاصطناعي ضد الأدلة + السجل", + "landing.step_2_desc": "البحث الهجين (كثيف + BM25 + إعادة الترتيب) يسترجع الوثائق ذات الصلة. ينتج LLM تشخيصاً مدعماً باستشهادات.", + "landing.step_3_title": "المشرف يوافق → يتم توجيه الفني", + "landing.step_3_desc": "يصل أمر العمل ثلاثي اللغات إلى قائمة الانتظار في لوحة التحكم. نقرة واحدة للموافقة. يتم إرسال الفني مع السياق الكامل.", + "landing.cta_title": "مستعد لرؤيته أثناء العمل؟", + "landing.cta_desc": "شغّل لوحة التحكم المباشرة لمشاهدة تدفق الأعطال عبر خط الأنابيب في الوقت الفعلي.", + "landing.cta_launch": "تشغيل لوحة التحكم", + "dashboard.title": "لوحة تحكم المشرف", "dashboard.subtitle": "قائمة الموافقات ومقاييس وقت التوقف", "dashboard.total": "إجمالي أوامر العمل", diff --git a/web/src/pages/LandingPage.jsx b/web/src/pages/LandingPage.jsx index 1a8ac6b..bee32d8 100644 --- a/web/src/pages/LandingPage.jsx +++ b/web/src/pages/LandingPage.jsx @@ -5,44 +5,9 @@ import PipelineDiagram from "../components/PipelineDiagram.jsx"; import FeatureCard from "../components/FeatureCard.jsx"; import { IconDiagnosis, IconDocument, IconPin, IconRefresh, IconBroadcast, IconArrowRight, IconArrowDown } from "../components/icons.jsx"; import Footer from "../components/Footer.jsx"; +import { useI18n } from "../i18n.jsx"; import styles from "./LandingPage.module.css"; -const features = [ - { - icon: , - title: "AI Diagnosis", - description: "Hybrid search across manuals and repair history pinpoints root causes in seconds, not hours.", - }, - { - icon: , - title: "Trilingual Work Orders", - description: "Every work order auto-generates in English, French, and Arabic as a downloadable PDF.", - }, - { - icon: , - title: "Smart Dispatch", - description: "Routes the right technician based on skill, location, and availability.", - }, - { - icon: , - title: "Self Learning", - description: "Every fix enriches the knowledge base. The model gets smarter with each resolved fault.", - }, - { - icon: , - title: "Works With Your Setup", - description: "Report faults from the dashboard, connect machines that send digital alerts, or bridge older equipment — no special hardware required.", - }, -]; - -const stats = [ - { value: "99.2", suffix: "%", label: "Diagnosis accuracy" }, - { value: "47", suffix: "s", label: "Avg time to diagnose" }, - { value: "1,240", suffix: "+", label: "Faults resolved" }, - { value: "12", suffix: "x", label: "Faster than manual triage" }, - { value: "0", suffix: "", label: "Data leakage" }, -]; - function useInView(threshold = 0.15) { const ref = useRef(null); const [inView, setInView] = useState(false); @@ -101,12 +66,49 @@ function SectionTitle({ children, subtitle }) { } export default function LandingPage() { + const { t } = useI18n(); const [statsRef, statsVisible] = useInView(0.3); const [pipelineRef, pipelineVisible] = useInView(0.1); const [featuresRef, featuresVisible] = useInView(0.1); const [stepsRef, stepsVisible] = useInView(0.1); const [problemsRef, problemsVisible] = useInView(0.1); + const features = [ + { + icon: , + title: t("landing.feature_1_title"), + description: t("landing.feature_1_desc"), + }, + { + icon: , + title: t("landing.feature_2_title"), + description: t("landing.feature_2_desc"), + }, + { + icon: , + title: t("landing.feature_3_title"), + description: t("landing.feature_3_desc"), + }, + { + icon: , + title: t("landing.feature_4_title"), + description: t("landing.feature_4_desc"), + }, + { + icon: , + title: t("landing.feature_5_title"), + description: t("landing.feature_5_desc"), + }, + ]; + + const stats = [ + { value: "99.2", suffix: "%", label: t("landing.stat_diag_accuracy") }, + { value: "47", suffix: "s", label: t("landing.stat_avg_time") }, + { value: "1,240", suffix: "+", label: t("landing.stat_faults_resolved") }, + { value: "12", suffix: "x", label: t("landing.stat_faster") }, + { value: "0", suffix: "", label: t("landing.stat_data_leakage") }, + ]; + return (
@@ -116,21 +118,21 @@ export default function LandingPage() {
- Fault to Fix Engine + {t("landing.badge")}

- From fault code
- to fixed. + {t("landing.hero_title_1")}
+ {t("landing.hero_title_2")}

- TORQ autonomously diagnoses machine faults, generates trilingual work orders, and dispatches the right technician all in real time. + {t("landing.hero_desc")}

- Live Demo + {t("landing.cta_demo")} - How it works + {t("landing.cta_how")}
@@ -141,20 +143,20 @@ export default function LandingPage() {
-

The Hidden Cost of Legacy Downtime

+

{t("landing.problems_headline")}

-

Hours lost to manual searches

-

Technicians waste hours digging though dusty, 500 page physical manuals or fragmented PDFs to translate a single PLC fault code.

+

{t("landing.problem_1_title")}

+

{t("landing.problem_1_desc")}

-

The tribal knowledge expiry

-

Critical maintenance workarounds live only in the heads of senior engineers. When they retire or exit the plant floor, operational wisdom is permanently lost.

+

{t("landing.problem_2_title")}

+

{t("landing.problem_2_desc")}

-

Trilingual friction

-

Mismatches between machine logs, manufacturer documentation, and technician field languages (English, French, Arabic) create costly communication bottlenecks.

+

{t("landing.problem_3_title")}

+

{t("landing.problem_3_desc")}

@@ -171,8 +173,8 @@ export default function LandingPage() { {/* ── Pipeline ── */}
- - How TORQ drives the repair + + {t("landing.pipeline_title")}
@@ -183,8 +185,8 @@ export default function LandingPage() { {/* ── Features ── */}
- - Features + + {t("landing.features_title")}
{features.map((f, i) => ( @@ -197,29 +199,29 @@ export default function LandingPage() { {/* ── How it works ── */}
- - How it works + + {t("landing.how_title")}
1
-

A fault comes in

-

A technician reports it from the dashboard, a connected machine sends an alert, or a bridge picks it up from older controllers. TORQ starts immediately, no matter how the fault arrives.

+

{t("landing.step_1_title")}

+

{t("landing.step_1_desc")}

2
-

AI diagnoses against manuals + history

-

Hybrid search (dense + BM25 + reranker) retrieves relevant documentation. A reasoning LLM produces a grounded diagnosis with citations.

+

{t("landing.step_2_title")}

+

{t("landing.step_2_desc")}

3
-

Supervisor approves → technician routed

-

The trilingual work order lands in the dashboard queue. One click to approve. The technician is dispatched with full context.

+

{t("landing.step_3_title")}

+

{t("landing.step_3_desc")}

@@ -229,10 +231,10 @@ export default function LandingPage() { {/* ── CTA ── */}
-

Ready to see it in action?

-

Launch the live dashboard to watch faults flow through the pipeline in real time.

+

{t("landing.cta_title")}

+

{t("landing.cta_desc")}

- Launch Dashboard + {t("landing.cta_launch")}
From 89a1af3c4a4be2d1606db1ab18e3554934bba3dd Mon Sep 17 00:00:00 2001 From: Adam Ridene Date: Sat, 18 Jul 2026 20:23:26 +0100 Subject: [PATCH 2/4] Fix RTL support - use CSS logical properties for landing page layout --- web/src/pages/LandingPage.module.css | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/web/src/pages/LandingPage.module.css b/web/src/pages/LandingPage.module.css index 119a6da..10583c4 100644 --- a/web/src/pages/LandingPage.module.css +++ b/web/src/pages/LandingPage.module.css @@ -88,14 +88,17 @@ .heroCorner { position: absolute; bottom: 0; - left: 0; - right: 0; + inset-inline: 0; height: 1px; background: linear-gradient(to right, transparent, var(--border-color), transparent); z-index: 1; transition: background 0.35s; } +[dir="rtl"] .heroCorner { + background: linear-gradient(to left, transparent, var(--border-color), transparent); +} + .heroContent { position: relative; z-index: 1; @@ -236,14 +239,14 @@ align-items: center; justify-content: center; padding: 32px 16px; - border-right: 1px solid var(--border-color); + border-inline-end: 1px solid var(--border-color); opacity: 0; transform: translateY(16px); transition: opacity 0.6s ease, transform 0.6s ease, border-color 0.35s; } .stat:last-child { - border-right: none; + border-inline-end: none; } .statVisible { @@ -271,7 +274,7 @@ font-weight: 500; font-size: 22px; color: var(--text-muted); - margin-left: 2px; + margin-inline-start: 2px; transition: color 0.35s; } @@ -311,13 +314,16 @@ content: ""; position: absolute; bottom: 0; - left: 10%; - right: 10%; + inset-inline: 10%; height: 1px; background: linear-gradient(to right, transparent, var(--border-color), transparent); transition: background 0.35s; } +[dir="rtl"] .howSection::after { + background: linear-gradient(to left, transparent, var(--border-color), transparent); +} + .steps { max-width: 580px; margin: 0 auto; @@ -332,7 +338,7 @@ position: absolute; top: 24px; bottom: 24px; - left: 19px; + inset-inline-start: 19px; width: 2px; background: var(--border-color); transition: background 0.35s; From a5ede0ffad82f213b4f3e54cb1b6064a64f839bf Mon Sep 17 00:00:00 2001 From: Adam Ridene Date: Sat, 18 Jul 2026 20:26:46 +0100 Subject: [PATCH 3/4] Translate Navbar, Footer, PipelineDiagram, FAQ - all sections now support AR/FR --- web/src/components/FAQ.jsx | 43 +++----- web/src/components/Footer.jsx | 34 ++++--- web/src/components/Navbar.jsx | 2 +- web/src/components/PipelineDiagram.jsx | 19 ++-- web/src/i18n.jsx | 135 +++++++++++++++++++++++++ 5 files changed, 177 insertions(+), 56 deletions(-) diff --git a/web/src/components/FAQ.jsx b/web/src/components/FAQ.jsx index c1ecc00..483c40b 100644 --- a/web/src/components/FAQ.jsx +++ b/web/src/components/FAQ.jsx @@ -1,40 +1,21 @@ import { useState } from "react"; +import { useI18n } from "../i18n"; import styles from "./FAQ.module.css"; -const items = [ - { - q: "What is TORQ?", - a: "TORQ is an event-driven predictive-maintenance pipeline. When a machine faults, the AI autonomously diagnoses the root cause, generates a trilingual work order, and dispatches the right technician \u2014 all in real time.", - }, - { - q: "How does the AI diagnosis work?", - a: "Hybrid search (dense + BM25 sparse + reranker) retrieves relevant manuals and past repairs. A reasoning LLM produces the diagnosis with grounded citations.", - }, - { - q: "What machines are supported?", - a: "Any machine. If your equipment sends digital alerts, TORQ can pick them up. If your machines are fully offline, operators can submit faults directly through the dashboard form or from any connected device.", - }, - { - q: "How do I integrate TORQ with my plant?", - a: "Four ways: (1) Use the dashboard form to report a fault manually. (2) Send fault data from your existing maintenance or ERP system. (3) Connect machines that already produce digital fault signals. (4) Run a small bridge on a device like a Raspberry Pi to connect older controllers — no special hardware required.", - }, - { - q: "Is my data secure?", - a: "TORQ runs on your infrastructure. LLM calls go to your endpoint. Vector DB can be self-hosted. No data leaves your network.", - }, - { - q: "What languages are supported?", - a: "English, French, and Arabic (trilingual work-order PDF). Dashboard and API in English.", - }, - { - q: "Is this production-ready?", - a: "Hackathon prototype demonstrating the architecture. Production deployment requires hardening, auth, and scalability testing.", - }, -]; - export default function FAQ({ dark }) { + const { t } = useI18n(); const [openIndex, setOpenIndex] = useState(null); + const items = [ + { q: t("faq.q1"), a: t("faq.a1") }, + { q: t("faq.q2"), a: t("faq.a2") }, + { q: t("faq.q3"), a: t("faq.a3") }, + { q: t("faq.q4"), a: t("faq.a4") }, + { q: t("faq.q5"), a: t("faq.a5") }, + { q: t("faq.q6"), a: t("faq.a6") }, + { q: t("faq.q7"), a: t("faq.a7") }, + ]; + return (
{items.map((item, i) => ( diff --git a/web/src/components/Footer.jsx b/web/src/components/Footer.jsx index 40f8d79..4b1a579 100644 --- a/web/src/components/Footer.jsx +++ b/web/src/components/Footer.jsx @@ -1,39 +1,41 @@ import { Link } from "react-router-dom"; import styles from "./Footer.module.css"; import FAQ from "./FAQ.jsx"; +import { useI18n } from "../i18n"; export default function Footer() { + const { t } = useI18n(); return (
-

Product

- Features - Pipeline - How it works - Dashboard +

{t("footer.product")}

+ {t("footer.features")} + {t("footer.pipeline")} + {t("footer.how_it_works")} + {t("footer.dashboard")}
-

Use Cases

- Manufacturing - Warehousing - Energy +

{t("footer.use_cases")}

+ {t("footer.manufacturing")} + {t("footer.warehousing")} + {t("footer.energy")}
-

Support

- Documentation - API Reference - Contact sales - Status +

{t("footer.support")}

+ {t("footer.documentation")} + {t("footer.api_reference")} + {t("footer.contact_sales")} + {t("footer.status")}
-

FAQ

+

{t("footer.faq")}

- TORQ · From fault code to fixed. Built for the factory floor. + {t("footer.tagline")}
diff --git a/web/src/components/Navbar.jsx b/web/src/components/Navbar.jsx index 9ba5f2b..dcade30 100644 --- a/web/src/components/Navbar.jsx +++ b/web/src/components/Navbar.jsx @@ -26,7 +26,7 @@ export default function Navbar() {
- Dashboard + {t("navbar.dashboard")}
{LANGS.map((l) => (