diff --git a/components/blocks/CompanyTimeline.tsx b/components/blocks/CompanyTimeline.tsx index 106cc3ee8..9d3af276f 100644 --- a/components/blocks/CompanyTimeline.tsx +++ b/components/blocks/CompanyTimeline.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { motion, useScroll, useTransform } from 'framer-motion'; import { Building2, Compass, Layers, ArrowDownToLine, Wrench, Factory, Zap, MapPin, CheckCircle2 } from 'lucide-react'; +import { useTranslations } from 'next-intl'; const iconMap: Record = { Building2, @@ -16,37 +17,6 @@ const iconMap: Record = { CheckCircle2 }; -const defaultMilestones = [ - { - date: '16.12.2015', - year: '2015', - title: 'Gründung E-TIB GmbH', - desc: 'Ausführung elektrischer Infrastrukturprojekte, Kabeltiefbau und Horizontalspülbohrungen.', - iconName: 'Building2', - }, - { - date: '04.02.2019', - year: '2019', - title: 'Gründung E-TIB Ingenieurgesellschaft', - desc: 'Genehmigungs- und Ausführungsplanung, komplexe Querungen sowie Netzanschlussplanung.', - iconName: 'Compass', - }, - { - date: '14.11.2019', - year: '2019', - title: 'Gründung E-TIB Verwaltung GmbH', - desc: 'Zentrale Dienste, Erwerb, Vermietung, Verpachtung und Verwaltung von Immobilien und Maschinen.', - iconName: 'Layers', - }, - { - date: '21.10.2025', - year: '2025', - title: 'Gründung E-TIB Bohrtechnik GmbH', - desc: 'Spezialisierung auf präzise Horizontalspülbohrungen in allen Bodenklassen.', - iconName: 'ArrowDownToLine', - }, -]; - interface Milestone { date: string; year: string; @@ -62,10 +32,45 @@ interface CompanyTimelineProps { } export function CompanyTimeline({ - badge = 'Unsere Geschichte', - title = 'Meilensteine der Entwicklung', - milestones = defaultMilestones + badge, + title, + milestones }: CompanyTimelineProps) { + const t = useTranslations('CompanyTimeline'); + + const finalBadge = badge || t('badge'); + const finalTitle = title || t('title'); + + const finalMilestones = milestones || [ + { + date: '16.12.2015', + year: '2015', + title: t('milestones.2015.title'), + desc: t('milestones.2015.desc'), + iconName: 'Building2', + }, + { + date: '04.02.2019', + year: '2019', + title: t('milestones.2019_ing.title'), + desc: t('milestones.2019_ing.desc'), + iconName: 'Compass', + }, + { + date: '14.11.2019', + year: '2019', + title: t('milestones.2019_verw.title'), + desc: t('milestones.2019_verw.desc'), + iconName: 'Layers', + }, + { + date: '21.10.2025', + year: '2025', + title: t('milestones.2025.title'), + desc: t('milestones.2025.desc'), + iconName: 'ArrowDownToLine', + }, + ]; const containerRef = React.useRef(null); const { scrollYProgress } = useScroll({ target: containerRef, @@ -84,10 +89,10 @@ export function CompanyTimeline({
- {badge} + {finalBadge}

- {title} + {finalTitle}

@@ -104,7 +109,7 @@ export function CompanyTimeline({
- {milestones.map((milestone, i) => { + {finalMilestones.map((milestone, i) => { const isEven = i % 2 === 0; const Icon = iconMap[milestone.iconName] || Building2; diff --git a/components/blocks/InteractiveGermanyMap.tsx b/components/blocks/InteractiveGermanyMap.tsx index 70d3923d2..50bdec2c5 100644 --- a/components/blocks/InteractiveGermanyMap.tsx +++ b/components/blocks/InteractiveGermanyMap.tsx @@ -7,7 +7,7 @@ import Image from 'next/image'; import { useRouter } from 'next/navigation'; import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder'; import { Location, defaultLocations, minorLocations } from '@/lib/map-data'; -import { useLocale } from 'next-intl'; +import { useLocale, useTranslations } from 'next-intl'; const allLocations = [...defaultLocations, ...minorLocations]; @@ -27,9 +27,9 @@ interface InteractiveGermanyMapProps { } export function InteractiveGermanyMap({ - badge = 'Einsatzgebiete', - title = <>Deutschlandweit
für Sie im Einsatz., - description = 'Von unseren strategischen Standorten in Guben und Bülstedt steuern und realisieren wir komplexe Infrastrukturprojekte im gesamten Bundesgebiet.', + badge, + title, + description, stats = [ { value: '100', suffix: '%', label: 'Überregionale Reichweite' }, { value: '2', suffix: '+', label: 'Operative Standorte' }, @@ -40,6 +40,13 @@ export function InteractiveGermanyMap({ const [activeLocation, setActiveLocation] = useState(null); const router = useRouter(); const locale = useLocale(); + const t = useTranslations('InteractiveGermanyMap'); + const tStandard = useTranslations('StandardPage'); + + const finalBadge = badge || tStandard('badge'); + // the map is mostly used with specific props, so we leave title & description to fallbacks if not provided + const finalTitle = title || (locale === 'en' ? <>Nationwide
in operation for you. : <>Deutschlandweit
für Sie im Einsatz.); + const finalDescription = description || (locale === 'en' ? 'From our strategic locations in Guben and Bülstedt, we control and implement complex infrastructure projects nationwide.' : 'Von unseren strategischen Standorten in Guben und Bülstedt steuern und realisieren wir komplexe Infrastrukturprojekte im gesamten Bundesgebiet.'); const hq = locations.find((l) => l.type === 'hq'); const branch = locations.find((l) => l.type === 'branch'); @@ -62,21 +69,21 @@ export function InteractiveGermanyMap({
- {badge} + {finalBadge}
{isHero ? (

- {title} + {finalTitle}

) : (

- {title} + {finalTitle}

)}

- {description} + {finalDescription}

{/* Industrial Stats Grid */} @@ -204,9 +211,7 @@ export function InteractiveGermanyMap({
- {activeLocation.type === 'hq' ? 'Hauptsitz' : - activeLocation.type === 'branch' ? 'Niederlassung' : - activeLocation.type === 'minor_node' ? 'Projekt' : 'Referenz'} + {t(`types.${activeLocation.type === 'minor_node' ? 'project' : activeLocation.type}`)}
@@ -218,12 +223,7 @@ export function InteractiveGermanyMap({
) : (
- {activeLocation.description === 'wind' ? 'Errichtung Leitungstrassen & Netzanbindung für Windpark-Infrastruktur.' : - activeLocation.description === 'pv' ? 'Bau von Mittelspannungstrassen zur Einspeisung der PV-Anlage.' : - activeLocation.description === 'fiber' ? 'Komplexer FTTx Breitbandausbau inkl. LWL-Montage & Tiefbau.' : - activeLocation.description === 'power' ? '110kV Hochspannungstrasse Erdkabelverlegung.' : - activeLocation.description === 'battery' ? 'Infrastrukturausbau für BESS (Batteriespeicher).' : - 'Komplexes Infrastrukturprojekt (Tiefbau & HDD).'} + {t(`descriptions.${['wind','pv','fiber','power','battery'].includes(activeLocation.description || '') ? activeLocation.description : 'default'}`)}
)} @@ -233,17 +233,11 @@ export function InteractiveGermanyMap({ <>
  • - { - activeLocation.description === 'wind' ? 'Netzanbindung Windpark' : - activeLocation.description === 'pv' ? 'Einspeisung PV-Anlage' : - activeLocation.description === 'fiber' ? 'FTTx Infrastruktur' : - activeLocation.description === 'power' ? '110kV Trasse' : - activeLocation.description === 'battery' ? 'BESS Anschluss' : 'Infrastrukturprojekt' - } + {t(`features.${['wind','pv','fiber','power','battery'].includes(activeLocation.description || '') ? activeLocation.description : 'default'}`)}
  • - Tiefbau & Spülbohrung (HDD) + {t('features.method')}
  • ) : ( @@ -259,7 +253,7 @@ export function InteractiveGermanyMap({ {activeLocation.href && (
    - {locale === 'en' ? 'Learn more' : 'Zum Projekt'} + {t('learnMore')}
    )} diff --git a/components/blocks/ReferencesSlider.test.tsx b/components/blocks/ReferencesSlider.test.tsx index 52937bc47..7c5fcca2a 100644 --- a/components/blocks/ReferencesSlider.test.tsx +++ b/components/blocks/ReferencesSlider.test.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { describe, it, expect, vi } from 'vitest'; import { render, screen, fireEvent } from '@testing-library/react'; import { ReferencesSlider, Reference } from './ReferencesSlider'; +import { NextIntlClientProvider } from 'next-intl'; // Mock next/link to render standard tag vi.mock('next/link', () => ({ @@ -21,6 +22,13 @@ vi.mock('next/image', () => ({ } })); +// Mock next-intl +vi.mock('next-intl', () => ({ + useTranslations: () => (key: string) => key, + useLocale: () => 'en', + NextIntlClientProvider: ({ children }: any) => <>{children} +})); + describe('ReferencesSlider TDD', () => { const mockReferences: Reference[] = [ { @@ -49,8 +57,8 @@ describe('ReferencesSlider TDD', () => { const links = screen.getAllByTestId('reference-tile-link'); expect(links).toHaveLength(2); - expect(links[0].getAttribute('href')).toBe('/referenzen/referenz-projekt-eins'); - expect(links[1].getAttribute('href')).toBe('/referenzen/referenz-projekt-zwei'); + expect(links[0].getAttribute('href')).toBe('/en/referenzen/referenz-projekt-eins'); + expect(links[1].getAttribute('href')).toBe('/en/referenzen/referenz-projekt-zwei'); }); it('allows navigation on simple click (no drag)', () => { diff --git a/components/blocks/ReferencesSlider.tsx b/components/blocks/ReferencesSlider.tsx index 7ec4757a6..b1cf00a27 100644 --- a/components/blocks/ReferencesSlider.tsx +++ b/components/blocks/ReferencesSlider.tsx @@ -5,6 +5,7 @@ import { motion } from 'framer-motion'; import Link from 'next/link'; import Image from 'next/image'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; +import { useTranslations, useLocale } from 'next-intl'; export interface Reference { id: string; @@ -34,6 +35,9 @@ interface ReferencesSliderProps { } export function ReferencesSlider(props: ReferencesSliderProps) { + const t = useTranslations('ReferencesSlider'); + const locale = useLocale(); + const { data } = props; const references = props.references || []; const containerRef = React.useRef(null); @@ -43,11 +47,11 @@ export function ReferencesSlider(props: ReferencesSliderProps) { const isDraggingRef = React.useRef(false); const [isDragging, setIsDragging] = React.useState(false); - const badge = props.badge || data?.badge || 'Ausgewählte Projekte'; - const title = props.title || data?.title || 'Referenzen & Erfolge'; - const description = props.description || data?.description || 'Ein Auszug unserer erfolgreich abgeschlossenen Projekte im Bereich Kabeltiefbau, Bohrtechnik und Netzinfrastruktur.'; - const ctaLabel = props.ctaLabel || data?.ctaLabel || 'Alle Referenzen ansehen'; - const ctaHref = props.ctaHref || data?.ctaHref || '/referenzen'; + const badge = props.badge || data?.badge || t('badge'); + const title = props.title || data?.title || t('title'); + const description = props.description || data?.description || t('description'); + const ctaLabel = props.ctaLabel || data?.ctaLabel || t('ctaLabel'); + const ctaHref = props.ctaHref || data?.ctaHref || `/${locale}/referenzen`; if (!references || references.length === 0) return null; @@ -132,7 +136,7 @@ export function ReferencesSlider(props: ReferencesSliderProps) { className="flex-shrink-0 w-[320px] md:w-[480px] snap-center group pointer-events-auto" > { vi.clearAllMocks(); }); - it('translates /en/events to /de/messen when switching to German', () => { - vi.mocked(usePathname).mockReturnValue('/en/events'); + it('translates /en/trade-fairs to /de/messen when switching to German', () => { + (usePathname as any).mockReturnValue('/en/trade-fairs'); render(); const deLink = screen.getByLabelText('Switch to Deutsch'); expect(deLink.getAttribute('href')).toBe('/de/messen'); }); - it('translates /de/messen to /en/events when switching to English', () => { - vi.mocked(usePathname).mockReturnValue('/de/messen'); + it('translates /de/messen to /en/trade-fairs when switching to English', () => { + (usePathname as any).mockReturnValue('/de/messen'); render(); const enLink = screen.getByLabelText('Switch to English'); - expect(enLink.getAttribute('href')).toBe('/en/events'); + expect(enLink.getAttribute('href')).toBe('/en/trade-fairs'); }); it('translates /en/about-us to /de/ueber-uns when switching to German', () => { diff --git a/content/de/ueber-uns.mdx b/content/de/ueber-uns.mdx index 7760ec7c2..cfd81f3e0 100644 --- a/content/de/ueber-uns.mdx +++ b/content/de/ueber-uns.mdx @@ -52,7 +52,7 @@ layout: "fullBleed"
    - + diff --git a/content/en/ueber-uns.mdx b/content/en/ueber-uns.mdx index 205380696..5d8133998 100644 --- a/content/en/ueber-uns.mdx +++ b/content/en/ueber-uns.mdx @@ -52,42 +52,9 @@ layout: "fullBleed" - + - +