refactor(i18n): cała treść landingu i /platforma przez useT()
Krok 1 z dwóch: przenosi stringi, nie tłumaczy ich. en.ts dostaje komplet kluczy z polską treścią — angielskie wartości wchodzą osobnym commitem, żeby diff tłumaczeń dało się czytać zdanie po zdaniu. - data/content.ts: zostaje sama struktura (id, icon, href). Ikony to komponenty Reacta i nie mogą wejść do słowników; kolejność i liczba kart są przez to zdefiniowane raz, a nie duplikowane per język. - i18n/types.ts + RichText: akapity z <strong>/<em> w środku zdania trzymamy jako listę przebiegów. Bez dangerouslySetInnerHTML — tłumaczenie nie może wstrzyknąć znaczników. - en.ts typowane jako `typeof pl`, więc rozjazd kluczy to błąd builda. Przy ~150 kluczach to główne ryzyko tej zmiany. - privacy.backToHome -> common.backToHome (używane przez obie podstrony). Weryfikacja: renderowany tekst porównany z produkcją na wszystkich sześciu trasach — identyczny, poza linkiem powrotnym na /en/platforma, który był zahardkodowany po polsku i teraz zgadza się z /en/privacy. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
13ffb8754b
commit
605bc3d025
|
|
@ -1,13 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { CheckCircle2 } from 'lucide-react';
|
import { CheckCircle2 } from 'lucide-react';
|
||||||
|
import { useT } from '../i18n';
|
||||||
|
|
||||||
const About = () => {
|
const About = () => {
|
||||||
const points = [
|
const t = useT();
|
||||||
"Strategia bez hype’u",
|
|
||||||
"Automatyzacje, które da się utrzymać",
|
|
||||||
"Agenci pod kontrolą człowieka"
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="about" className="py-24 relative overflow-hidden">
|
<section id="about" className="py-24 relative overflow-hidden">
|
||||||
|
|
@ -19,14 +16,11 @@ const About = () => {
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.6 }}
|
||||||
>
|
>
|
||||||
<h2 className="text-3xl md:text-4xl font-bold mb-8">Czym jest humanAI?</h2>
|
<h2 className="text-3xl md:text-4xl font-bold mb-8">{t.about.title}</h2>
|
||||||
<p className="text-xl text-muted leading-relaxed mb-12">
|
<p className="text-xl text-muted leading-relaxed mb-12">{t.about.lead}</p>
|
||||||
humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe.
|
|
||||||
Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-6">
|
<div className="grid md:grid-cols-3 gap-6">
|
||||||
{points.map((point, index) => (
|
{t.about.points.map((point, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={index}
|
key={index}
|
||||||
initial={{ opacity: 0, y: 10 }}
|
initial={{ opacity: 0, y: 10 }}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { audience } from '../data/content';
|
|
||||||
import { UserCheck } from 'lucide-react';
|
import { UserCheck } from 'lucide-react';
|
||||||
|
import { useT } from '../i18n';
|
||||||
|
|
||||||
const Audience = () => {
|
const Audience = () => {
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-24 relative overflow-hidden">
|
<section className="py-24 relative overflow-hidden">
|
||||||
<div className="container mx-auto px-6">
|
<div className="container mx-auto px-6">
|
||||||
<div className="mb-16 text-center">
|
<div className="mb-16 text-center">
|
||||||
<h2 className="text-3xl md:text-5xl font-bold mb-6">Dla kogo</h2>
|
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.audience.title}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap justify-center gap-6">
|
<div className="flex flex-wrap justify-center gap-6">
|
||||||
{audience.map((item, index) => (
|
{t.audience.items.map((item, index) => (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={index}
|
key={index}
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
|
|
||||||
|
|
@ -100,12 +100,8 @@ const CTASection = () => {
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-12 relative z-10">
|
<div className="grid md:grid-cols-2 gap-12 relative z-10">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-4xl font-bold mb-6">
|
<h2 className="text-4xl font-bold mb-6">{t.cta.title}</h2>
|
||||||
Masz proces, który powinien już pracować sam?
|
<p className="text-xl text-muted mb-8">{t.cta.lead}</p>
|
||||||
</h2>
|
|
||||||
<p className="text-xl text-muted mb-8">
|
|
||||||
Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.
|
|
||||||
</p>
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center gap-3 text-primary">
|
<div className="flex items-center gap-3 text-primary">
|
||||||
<Mail size={20} />
|
<Mail size={20} />
|
||||||
|
|
@ -119,9 +115,7 @@ const CTASection = () => {
|
||||||
support@gethumanai.pl
|
support@gethumanai.pl
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted italic">
|
<p className="text-sm text-muted italic">{t.cta.quote}</p>
|
||||||
"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { localizePath, stripLangPrefix, useLang } from '../i18n';
|
import { localizePath, stripLangPrefix, useLang, useT } from '../i18n';
|
||||||
|
|
||||||
const Footer = () => {
|
const Footer = () => {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
// Same reasoning as the /#section nav links below: this footer is shared with
|
// Same reasoning as the /#section nav links below: this footer is shared with
|
||||||
// /privacy and /platforma, so the logo needs a real href to get home from
|
// /privacy and /platforma, so the logo needs a real href to get home from
|
||||||
|
|
@ -24,9 +25,7 @@ const Footer = () => {
|
||||||
<a href={localizePath('/', lang)} onClick={handleLogoClick} className="text-2xl font-bold tracking-tight mb-4 block">
|
<a href={localizePath('/', lang)} onClick={handleLogoClick} className="text-2xl font-bold tracking-tight mb-4 block">
|
||||||
human<span className="text-primary">AI</span>
|
human<span className="text-primary">AI</span>
|
||||||
</a>
|
</a>
|
||||||
<p className="text-muted max-w-xs mb-6">
|
<p className="text-muted max-w-xs mb-6">{t.footer.tagline}</p>
|
||||||
ludzka strona AI — budujemy praktyczne systemy AI dla ludzi i organizacji.
|
|
||||||
</p>
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<a href="mailto:hello@gethumanai.pl" className="text-foreground/80 hover:text-primary transition-colors">
|
<a href="mailto:hello@gethumanai.pl" className="text-foreground/80 hover:text-primary transition-colors">
|
||||||
hello@gethumanai.pl
|
hello@gethumanai.pl
|
||||||
|
|
@ -38,25 +37,25 @@ const Footer = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">Nawigacja</h4>
|
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">{t.footer.navHeading}</h4>
|
||||||
<ul className="space-y-4">
|
<ul className="space-y-4">
|
||||||
<li><a href={localizePath('/#offerings', lang)} className="text-muted hover:text-foreground transition-colors">Oferta</a></li>
|
<li><a href={localizePath('/#offerings', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.offerings}</a></li>
|
||||||
<li><a href={localizePath('/platforma', lang)} className="text-muted hover:text-foreground transition-colors">Platforma</a></li>
|
<li><a href={localizePath('/platforma', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.platform}</a></li>
|
||||||
<li><a href={localizePath('/#contact', lang)} className="text-muted hover:text-foreground transition-colors">Kontakt</a></li>
|
<li><a href={localizePath('/#contact', lang)} className="text-muted hover:text-foreground transition-colors">{t.nav.contact}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">Prywatność</h4>
|
<h4 className="font-bold mb-6 text-sm uppercase tracking-wider">{t.footer.privacyHeading}</h4>
|
||||||
<ul className="space-y-4">
|
<ul className="space-y-4">
|
||||||
<li><a href={localizePath('/privacy', lang)} className="text-muted hover:text-foreground transition-colors">Polityka prywatności</a></li>
|
<li><a href={localizePath('/privacy', lang)} className="text-muted hover:text-foreground transition-colors">{t.footer.privacyPolicy}</a></li>
|
||||||
<li><a href={localizePath('/privacy#cookies', lang)} className="text-muted hover:text-foreground transition-colors">Cookies</a></li>
|
<li><a href={localizePath('/privacy#cookies', lang)} className="text-muted hover:text-foreground transition-colors">{t.footer.cookies}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="pt-8 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-4 text-sm text-muted">
|
<div className="pt-8 border-t border-white/5 flex flex-col md:flex-row justify-between items-center gap-4 text-sm text-muted">
|
||||||
<p>© {currentYear} humanAI. Wszelkie prawa zastrzeżone.</p>
|
<p>© {currentYear} humanAI. {t.footer.rights}</p>
|
||||||
<div className="flex gap-8">
|
<div className="flex gap-8">
|
||||||
<span className="hover:text-foreground transition-colors cursor-pointer">LinkedIn</span>
|
<span className="hover:text-foreground transition-colors cursor-pointer">LinkedIn</span>
|
||||||
<span className="hover:text-foreground transition-colors cursor-pointer">X / Twitter</span>
|
<span className="hover:text-foreground transition-colors cursor-pointer">X / Twitter</span>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Menu, X } from 'lucide-react';
|
import { Menu, X } from 'lucide-react';
|
||||||
import { motion, AnimatePresence } from 'framer-motion';
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { localizePath, useLang } from '../i18n';
|
import { localizePath, useLang, useT } from '../i18n';
|
||||||
import LangSwitcher from './LangSwitcher';
|
import LangSwitcher from './LangSwitcher';
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
const t = useT();
|
||||||
const [isScrolled, setIsScrolled] = useState(false);
|
const [isScrolled, setIsScrolled] = useState(false);
|
||||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
|
@ -19,13 +20,12 @@ const Header = () => {
|
||||||
|
|
||||||
// Root-relative so the links also work from the standalone pages (/privacy,
|
// Root-relative so the links also work from the standalone pages (/privacy,
|
||||||
// /platforma), where these sections do not exist — and localized so they keep
|
// /platforma), where these sections do not exist — and localized so they keep
|
||||||
// the visitor on the language they are currently reading. Labels stay Polish
|
// the visitor on the language they are currently reading.
|
||||||
// until the section copy itself is translated.
|
|
||||||
const navLinks = [
|
const navLinks = [
|
||||||
{ name: 'Oferta', href: localizePath('/#offerings', lang) },
|
{ name: t.nav.offerings, href: localizePath('/#offerings', lang) },
|
||||||
{ name: 'Platforma', href: localizePath('/platforma', lang) },
|
{ name: t.nav.platform, href: localizePath('/platforma', lang) },
|
||||||
{ name: 'Proces', href: localizePath('/#process', lang) },
|
{ name: t.nav.process, href: localizePath('/#process', lang) },
|
||||||
{ name: 'Kontakt', href: localizePath('/#contact', lang) },
|
{ name: t.nav.contact, href: localizePath('/#contact', lang) },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -51,7 +51,7 @@ const Header = () => {
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
<a href={localizePath('/#contact', lang)} className="btn-primary text-sm px-5 py-2">
|
<a href={localizePath('/#contact', lang)} className="btn-primary text-sm px-5 py-2">
|
||||||
Porozmawiajmy
|
{t.nav.cta}
|
||||||
</a>
|
</a>
|
||||||
<LangSwitcher />
|
<LangSwitcher />
|
||||||
</nav>
|
</nav>
|
||||||
|
|
@ -90,7 +90,7 @@ const Header = () => {
|
||||||
className="btn-primary text-center"
|
className="btn-primary text-center"
|
||||||
onClick={() => setIsMobileMenuOpen(false)}
|
onClick={() => setIsMobileMenuOpen(false)}
|
||||||
>
|
>
|
||||||
Porozmawiajmy
|
{t.nav.cta}
|
||||||
</a>
|
</a>
|
||||||
<div className="pt-2 border-t border-white/10">
|
<div className="pt-2 border-t border-white/10">
|
||||||
<LangSwitcher onSwitch={() => setIsMobileMenuOpen(false)} />
|
<LangSwitcher onSwitch={() => setIsMobileMenuOpen(false)} />
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { ArrowRight } from 'lucide-react';
|
import { ArrowRight } from 'lucide-react';
|
||||||
|
import { useT } from '../i18n';
|
||||||
|
|
||||||
const Hero = () => {
|
const Hero = () => {
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="relative min-h-screen flex items-center pt-20 overflow-hidden">
|
<section className="relative min-h-screen flex items-center pt-20 overflow-hidden">
|
||||||
{/* Background elements */}
|
{/* Background elements */}
|
||||||
|
|
@ -17,18 +20,20 @@ const Hero = () => {
|
||||||
transition={{ duration: 0.6 }}
|
transition={{ duration: 0.6 }}
|
||||||
>
|
>
|
||||||
<h1 className="text-5xl md:text-7xl font-extrabold leading-tight mb-6">
|
<h1 className="text-5xl md:text-7xl font-extrabold leading-tight mb-6">
|
||||||
Budujemy <span className="text-gradient">ludzką stronę</span> AI
|
{t.hero.titleBefore}
|
||||||
|
<span className="text-gradient">{t.hero.titleAccent}</span>
|
||||||
|
{t.hero.titleAfter}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg md:text-xl text-muted mb-10 max-w-lg leading-relaxed">
|
<p className="text-lg md:text-xl text-muted mb-10 max-w-lg leading-relaxed">
|
||||||
Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej — od automatyzacji po multiagentowe platformy produktowe.
|
{t.hero.subtitle}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex flex-col sm:flex-row gap-4">
|
<div className="flex flex-col sm:flex-row gap-4">
|
||||||
<a href="#contact" className="btn-primary">
|
<a href="#contact" className="btn-primary">
|
||||||
Zacznijmy od audytu AI
|
{t.hero.ctaPrimary}
|
||||||
<ArrowRight className="ml-2" size={20} />
|
<ArrowRight className="ml-2" size={20} />
|
||||||
</a>
|
</a>
|
||||||
<a href="#offerings" className="btn-secondary">
|
<a href="#offerings" className="btn-secondary">
|
||||||
Zobacz ofertę
|
{t.hero.ctaSecondary}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,29 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { offerings } from '../data/content';
|
import { offerings } from '../data/content';
|
||||||
|
import type { OfferingId } from '../data/content';
|
||||||
|
import { localizePath, useLang, useT } from '../i18n';
|
||||||
import { ArrowRight, ChevronRight } from 'lucide-react';
|
import { ArrowRight, ChevronRight } from 'lucide-react';
|
||||||
|
import type { LucideIcon } from 'lucide-react';
|
||||||
|
|
||||||
const OfferingCard = ({ offering, index }: { offering: any, index: number }) => {
|
type Copy = {
|
||||||
const Icon = offering.icon;
|
title: string;
|
||||||
|
description: string;
|
||||||
|
points: readonly string[];
|
||||||
|
linkLabel?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const OfferingCard = ({
|
||||||
|
copy,
|
||||||
|
icon: Icon,
|
||||||
|
href,
|
||||||
|
index,
|
||||||
|
}: {
|
||||||
|
copy: Copy;
|
||||||
|
icon: LucideIcon;
|
||||||
|
href?: string;
|
||||||
|
index: number;
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, y: 30 }}
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
|
@ -17,24 +35,24 @@ const OfferingCard = ({ offering, index }: { offering: any, index: number }) =>
|
||||||
<div className="w-14 h-14 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6 group-hover:scale-110 transition-transform duration-500">
|
<div className="w-14 h-14 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6 group-hover:scale-110 transition-transform duration-500">
|
||||||
<Icon size={28} />
|
<Icon size={28} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-2xl font-bold mb-4">{offering.title}</h3>
|
<h3 className="text-2xl font-bold mb-4">{copy.title}</h3>
|
||||||
<p className="text-muted mb-8 leading-relaxed">
|
<p className="text-muted mb-8 leading-relaxed">
|
||||||
{offering.description}
|
{copy.description}
|
||||||
</p>
|
</p>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3">
|
||||||
{offering.points.map((point: string, i: number) => (
|
{copy.points.map((point, i) => (
|
||||||
<li key={i} className="flex items-center text-sm text-foreground/80">
|
<li key={i} className="flex items-center text-sm text-foreground/80">
|
||||||
<ChevronRight className="text-primary mr-2" size={16} />
|
<ChevronRight className="text-primary mr-2" size={16} />
|
||||||
{point}
|
{point}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
{offering.link && (
|
{href && copy.linkLabel && (
|
||||||
<a
|
<a
|
||||||
href={offering.link.href}
|
href={href}
|
||||||
className="mt-8 inline-flex items-center text-sm font-semibold text-primary hover:underline"
|
className="mt-8 inline-flex items-center text-sm font-semibold text-primary hover:underline"
|
||||||
>
|
>
|
||||||
{offering.link.label}
|
{copy.linkLabel}
|
||||||
<ArrowRight className="ml-2" size={16} />
|
<ArrowRight className="ml-2" size={16} />
|
||||||
</a>
|
</a>
|
||||||
)}
|
)}
|
||||||
|
|
@ -43,19 +61,29 @@ const OfferingCard = ({ offering, index }: { offering: any, index: number }) =>
|
||||||
};
|
};
|
||||||
|
|
||||||
const Offerings = () => {
|
const Offerings = () => {
|
||||||
|
const t = useT();
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="offerings" className="py-24 relative bg-surface/30">
|
<section id="offerings" className="py-24 relative bg-surface/30">
|
||||||
<div className="container mx-auto px-6">
|
<div className="container mx-auto px-6">
|
||||||
<div className="mb-16">
|
<div className="mb-16">
|
||||||
<h2 className="text-3xl md:text-5xl font-bold mb-6">Nasza Oferta</h2>
|
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.offerings.title}</h2>
|
||||||
<p className="text-xl text-muted max-w-2xl">
|
<p className="text-xl text-muted max-w-2xl">
|
||||||
Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.
|
{t.offerings.lead}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 gap-8">
|
<div className="grid md:grid-cols-2 gap-8">
|
||||||
{offerings.map((offering, index) => (
|
{offerings.map((offering, index) => (
|
||||||
<OfferingCard key={offering.id} offering={offering} index={index} />
|
<OfferingCard
|
||||||
|
key={offering.id}
|
||||||
|
icon={offering.icon}
|
||||||
|
// Structure lives in content.ts, copy in i18n — joined by id.
|
||||||
|
copy={t.offerings.items[offering.id as OfferingId]}
|
||||||
|
href={'link' in offering ? localizePath(offering.link.href, lang) : undefined}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,28 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ArrowRight, Building2, CheckCircle2, ChevronRight, Home } from 'lucide-react';
|
import { ArrowRight, Building2, CheckCircle2, ChevronRight, Home } from 'lucide-react';
|
||||||
import Footer from './Footer';
|
import Footer from './Footer';
|
||||||
import { localizePath, useLang } from '../i18n';
|
import RichText from './RichText';
|
||||||
|
import { localizePath, useLang, useT } from '../i18n';
|
||||||
|
import type { Bullet } from '../i18n/types';
|
||||||
import LangSwitcher from './LangSwitcher';
|
import LangSwitcher from './LangSwitcher';
|
||||||
|
|
||||||
// Standalone product page at /platforma (and /en/platforma). The copy is not
|
// Standalone product page at /platforma (and /en/platforma). All copy lives in
|
||||||
// localized yet — the site only translates contact.* and privacy.* — but the
|
// i18n under `platform`; paragraphs that carry inline emphasis are stored as
|
||||||
// links are, so reaching this page from /en does not strand you in Polish.
|
// runs and rendered through <RichText> (see i18n/types.ts).
|
||||||
const PlatformPage = () => {
|
const PlatformPage = () => {
|
||||||
|
const t = useT();
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
|
|
||||||
|
const renderBullet = (bullet: Bullet, i: number, Icon: typeof ChevronRight) => (
|
||||||
|
<li key={i} className="flex gap-3">
|
||||||
|
<Icon className="text-primary shrink-0 mt-1" size={18} />
|
||||||
|
<span className="text-foreground/80 leading-relaxed">
|
||||||
|
{bullet.lead && <strong className="text-foreground font-semibold">{bullet.lead}</strong>}
|
||||||
|
{bullet.body && <RichText content={bullet.body} />}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background selection:bg-primary selection:text-background">
|
<div className="min-h-screen bg-background selection:bg-primary selection:text-background">
|
||||||
<header className="bg-background/80 backdrop-blur-lg border-b border-white/5">
|
<header className="bg-background/80 backdrop-blur-lg border-b border-white/5">
|
||||||
|
|
@ -19,7 +32,7 @@ const PlatformPage = () => {
|
||||||
</a>
|
</a>
|
||||||
<div className="flex items-center gap-6">
|
<div className="flex items-center gap-6">
|
||||||
<a href={localizePath('/', lang)} className="text-sm text-muted hover:text-foreground transition-colors">
|
<a href={localizePath('/', lang)} className="text-sm text-muted hover:text-foreground transition-colors">
|
||||||
← Wróć na stronę główną
|
{t.common.backToHome}
|
||||||
</a>
|
</a>
|
||||||
<LangSwitcher />
|
<LangSwitcher />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -27,83 +40,42 @@ const PlatformPage = () => {
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container mx-auto px-6 py-16 max-w-3xl">
|
<main className="container mx-auto px-6 py-16 max-w-3xl">
|
||||||
<h1 className="text-4xl md:text-5xl font-bold mb-3">Nadzór nad systemami agentowymi</h1>
|
<h1 className="text-4xl md:text-5xl font-bold mb-3">{t.platform.title}</h1>
|
||||||
<p className="text-muted text-sm italic mb-16">
|
<p className="text-muted text-sm italic mb-16">{t.platform.workingName}</p>
|
||||||
(nazwa robocza — do potwierdzenia przed publikacją)
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="space-y-16">
|
<div className="space-y-16">
|
||||||
{/* ── Kto pilnuje agentów ───────────────────────────────────────── */}
|
{/* ── Kto pilnuje agentów ───────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.watchers.title}</h2>
|
||||||
Kto pilnuje agentów, którzy pilnują wszystkiego innego?
|
{t.platform.watchers.paragraphs.map((paragraph, i) => (
|
||||||
</h2>
|
<p key={i} className="text-foreground/80 leading-relaxed mb-4 last:mb-0">
|
||||||
<p className="text-foreground/80 leading-relaxed mb-4">
|
<RichText content={paragraph} />
|
||||||
{'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który '}
|
|
||||||
<strong className="text-foreground font-semibold">
|
|
||||||
obserwuje inne systemy — w tym inne systemy agentowe
|
|
||||||
</strong>
|
|
||||||
{' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.'}
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground/80 leading-relaxed">
|
|
||||||
{'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.'}
|
|
||||||
</p>
|
</p>
|
||||||
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── Problem, który znika ──────────────────────────────────────── */}
|
{/* ── Problem, który znika ──────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">Problem, który znika</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.problem.title}</h2>
|
||||||
<ul className="space-y-4">
|
<ul className="space-y-4">
|
||||||
<li className="flex gap-3">
|
{t.platform.problem.bullets.map((bullet, i) => renderBullet(bullet, i, ChevronRight))}
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Autonomia bez ram to ryzyko.</strong>
|
|
||||||
{' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Automatyka to nie inteligencja.</strong>
|
|
||||||
{' Wiele domów i firm ma już systemy, które '}
|
|
||||||
<em>wykonują</em>
|
|
||||||
{' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie '}
|
|
||||||
<em>rozumie</em>
|
|
||||||
{': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Wiedza znika.</strong>
|
|
||||||
{' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── Jak to działa ─────────────────────────────────────────────── */}
|
{/* ── Jak to działa ─────────────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">Jak to działa</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.howItWorks.title}</h2>
|
||||||
|
|
||||||
<p className="text-foreground/80 leading-relaxed mb-4">
|
<p className="text-foreground/80 leading-relaxed mb-4">
|
||||||
<strong className="text-foreground font-semibold">
|
<RichText content={t.platform.howItWorks.core} />
|
||||||
Rdzeń nadzoru — jeden, wspólny dla wszystkiego.
|
|
||||||
</strong>
|
|
||||||
{' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.'}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-foreground/80 leading-relaxed mb-10">
|
<p className="text-foreground/80 leading-relaxed mb-10">
|
||||||
{'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: '}
|
<RichText content={t.platform.howItWorks.humanAsk} />
|
||||||
<em className="text-foreground">{'„Nie zamknąłeś rolet. Zamknąć teraz?"'}</em>
|
|
||||||
{' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.'}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p className="text-foreground/80 leading-relaxed mb-8">
|
<p className="text-foreground/80 leading-relaxed mb-8">
|
||||||
<strong className="text-foreground font-semibold">
|
<RichText content={t.platform.howItWorks.tailored} />
|
||||||
System roboczy — budowany pod Ciebie.
|
|
||||||
</strong>
|
|
||||||
{' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.'}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Dwie ścieżki, jeden rdzeń — karty obok siebie */}
|
{/* Dwie ścieżki, jeden rdzeń — karty obok siebie */}
|
||||||
|
|
@ -112,11 +84,9 @@ const PlatformPage = () => {
|
||||||
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6">
|
<div className="w-12 h-12 rounded-xl bg-primary/10 flex items-center justify-center text-primary mb-6">
|
||||||
<Home size={24} />
|
<Home size={24} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4">Dla domu</h3>
|
<h3 className="text-xl font-bold mb-4">{t.platform.howItWorks.home.title}</h3>
|
||||||
<p className="text-foreground/80 leading-relaxed">
|
<p className="text-foreground/80 leading-relaxed">
|
||||||
{'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która '}
|
<RichText content={t.platform.howItWorks.home.body} />
|
||||||
<strong className="text-foreground font-semibold">rozumie kontekst</strong>
|
|
||||||
{': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.'}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -124,116 +94,52 @@ const PlatformPage = () => {
|
||||||
<div className="w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center text-secondary mb-6">
|
<div className="w-12 h-12 rounded-xl bg-secondary/10 flex items-center justify-center text-secondary mb-6">
|
||||||
<Building2 size={24} />
|
<Building2 size={24} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-xl font-bold mb-4">Dla firm</h3>
|
<h3 className="text-xl font-bold mb-4">{t.platform.howItWorks.business.title}</h3>
|
||||||
<p className="text-foreground/80 leading-relaxed">
|
<p className="text-foreground/80 leading-relaxed">
|
||||||
{'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.'}
|
<RichText content={t.platform.howItWorks.business.body} />
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className="text-foreground/80 leading-relaxed mt-8">
|
<p className="text-foreground/80 leading-relaxed mt-8">
|
||||||
{'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.'}
|
<RichText content={t.platform.howItWorks.shared} />
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── Pod maską ─────────────────────────────────────────────────── */}
|
{/* ── Pod maską ─────────────────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">Pod maską — dla ciekawych</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.underTheHood.title}</h2>
|
||||||
<ul className="space-y-4">
|
<ul className="space-y-4">
|
||||||
<li className="flex gap-3">
|
{t.platform.underTheHood.bullets.map((bullet, i) => renderBullet(bullet, i, ChevronRight))}
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
{'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje '}
|
|
||||||
<strong className="text-foreground font-semibold">
|
|
||||||
czytelna, kompilowana wiki utrzymywana przez model językowy
|
|
||||||
</strong>
|
|
||||||
{' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
{'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
{'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<ChevronRight className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
{'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── Dlaczego to ───────────────────────────────────────────────── */}
|
{/* ── Dlaczego to ───────────────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.why.title}</h2>
|
||||||
Dlaczego to, a nie zwykły monitoring czy zwykła automatyka
|
|
||||||
</h2>
|
|
||||||
<ul className="space-y-4">
|
<ul className="space-y-4">
|
||||||
<li className="flex gap-3">
|
{t.platform.why.bullets.map((bullet, i) => renderBullet(bullet, i, CheckCircle2))}
|
||||||
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">
|
|
||||||
Rozumiemy kontekst, nie tylko wykonujemy polecenia.
|
|
||||||
</strong>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Naprawiamy, nie tylko alarmujemy.</strong>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Człowiek naprawdę jest w pętli</strong>
|
|
||||||
{' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Zero czarnej skrzynki.</strong>
|
|
||||||
{' Każda decyzja zostawia ślad, który można później przejrzeć.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
<li className="flex gap-3">
|
|
||||||
<CheckCircle2 className="text-primary shrink-0 mt-1" size={18} />
|
|
||||||
<span className="text-foreground/80 leading-relaxed">
|
|
||||||
<strong className="text-foreground font-semibold">Twoje dane zostają Twoje</strong>
|
|
||||||
{' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.'}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── Gdzie jesteśmy ────────────────────────────────────────────── */}
|
{/* ── Gdzie jesteśmy ────────────────────────────────────────────── */}
|
||||||
<section>
|
<section>
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">Uczciwie o tym, gdzie jesteśmy</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.status.title}</h2>
|
||||||
<p className="text-foreground/80 leading-relaxed mb-4">
|
{t.platform.status.paragraphs.map((paragraph, i) => (
|
||||||
{'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.'}
|
<p key={i} className="text-foreground/80 leading-relaxed mb-4 last:mb-0">
|
||||||
</p>
|
<RichText content={paragraph} />
|
||||||
<p className="text-foreground/80 leading-relaxed">
|
|
||||||
{'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.'}
|
|
||||||
</p>
|
</p>
|
||||||
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* ── CTA ───────────────────────────────────────────────────────── */}
|
{/* ── CTA ───────────────────────────────────────────────────────── */}
|
||||||
<section className="glass-card p-10 text-center">
|
<section className="glass-card p-10 text-center">
|
||||||
<h2 className="text-2xl md:text-3xl font-bold mb-6">Umów rozmowę</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6">{t.platform.cta.title}</h2>
|
||||||
<p className="text-foreground/80 leading-relaxed mb-8">
|
<p className="text-foreground/80 leading-relaxed mb-8">
|
||||||
{'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.'}
|
<RichText content={t.platform.cta.body} />
|
||||||
</p>
|
</p>
|
||||||
<a href={localizePath('/#contact', lang)} className="btn-primary">
|
<a href={localizePath('/#contact', lang)} className="btn-primary">
|
||||||
Porozmawiajmy
|
{t.platform.cta.button}
|
||||||
<ArrowRight className="ml-2" size={20} />
|
<ArrowRight className="ml-2" size={20} />
|
||||||
</a>
|
</a>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ const PrivacyPolicyPage = () => {
|
||||||
</a>
|
</a>
|
||||||
<div className="flex items-center gap-6">
|
<div className="flex items-center gap-6">
|
||||||
<a href={home} className="text-sm text-muted hover:text-foreground transition-colors">
|
<a href={home} className="text-sm text-muted hover:text-foreground transition-colors">
|
||||||
{t.privacy.backToHome}
|
{t.common.backToHome}
|
||||||
</a>
|
</a>
|
||||||
<LangSwitcher />
|
<LangSwitcher />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,16 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { processSteps } from '../data/content';
|
import { processSteps } from '../data/content';
|
||||||
|
import { useT } from '../i18n';
|
||||||
|
|
||||||
const Process = () => {
|
const Process = () => {
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section id="process" className="py-24 relative bg-surface/50">
|
<section id="process" className="py-24 relative bg-surface/50">
|
||||||
<div className="container mx-auto px-6">
|
<div className="container mx-auto px-6">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-3xl md:text-5xl font-bold mb-6">Od pomysłu do działającego systemu</h2>
|
<h2 className="text-3xl md:text-5xl font-bold mb-6">{t.process.title}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
|
|
@ -30,8 +33,10 @@ const Process = () => {
|
||||||
<Icon size={28} />
|
<Icon size={28} />
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<span className="text-xs font-bold text-primary uppercase tracking-wider mb-2 block">Krok {step.id}</span>
|
<span className="text-xs font-bold text-primary uppercase tracking-wider mb-2 block">
|
||||||
<h3 className="text-xl font-bold">{step.title}</h3>
|
{t.process.stepLabel} {step.number}
|
||||||
|
</span>
|
||||||
|
<h3 className="text-xl font-bold">{t.process.steps[step.id]}</h3>
|
||||||
</div>
|
</div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
36
src/components/RichText.tsx
Normal file
36
src/components/RichText.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
import React from 'react';
|
||||||
|
import type { Rich } from '../i18n/types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders copy that carries inline emphasis (see i18n/types.ts). Keeps the
|
||||||
|
* dictionaries free of markup: no dangerouslySetInnerHTML, so a translation can
|
||||||
|
* never inject elements.
|
||||||
|
*/
|
||||||
|
const RichText = ({ content }: { content: Rich }) => {
|
||||||
|
if (typeof content === 'string') return <>{content}</>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{content.map((run, i) => {
|
||||||
|
if (run.em === 'strong') {
|
||||||
|
return (
|
||||||
|
<strong key={i} className="text-foreground font-semibold">
|
||||||
|
{run.t}
|
||||||
|
</strong>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (run.em === 'quote') {
|
||||||
|
return (
|
||||||
|
<em key={i} className="text-foreground">
|
||||||
|
{run.t}
|
||||||
|
</em>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (run.em === 'em') return <em key={i}>{run.t}</em>;
|
||||||
|
return <React.Fragment key={i}>{run.t}</React.Fragment>;
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RichText;
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
import { whyHumanAI } from '../data/content';
|
import { whyHumanAI } from '../data/content';
|
||||||
|
import { useT } from '../i18n';
|
||||||
|
|
||||||
const WhyHumanAI = () => {
|
const WhyHumanAI = () => {
|
||||||
|
const t = useT();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-24 relative overflow-hidden">
|
<section className="py-24 relative overflow-hidden">
|
||||||
<div className="container mx-auto px-6">
|
<div className="container mx-auto px-6">
|
||||||
|
|
@ -13,7 +16,7 @@ const WhyHumanAI = () => {
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
className="text-3xl md:text-5xl font-bold mb-8"
|
className="text-3xl md:text-5xl font-bold mb-8"
|
||||||
>
|
>
|
||||||
AI nie powinno być czarną skrzynką
|
{t.why.title}
|
||||||
</motion.h2>
|
</motion.h2>
|
||||||
<motion.p
|
<motion.p
|
||||||
initial={{ opacity: 0, y: 20 }}
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
|
@ -22,8 +25,7 @@ const WhyHumanAI = () => {
|
||||||
transition={{ delay: 0.1 }}
|
transition={{ delay: 0.1 }}
|
||||||
className="text-xl text-muted leading-relaxed"
|
className="text-xl text-muted leading-relaxed"
|
||||||
>
|
>
|
||||||
Najlepsze wdrożenia AI są zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy,
|
{t.why.lead}
|
||||||
które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.
|
|
||||||
</motion.p>
|
</motion.p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -32,7 +34,7 @@ const WhyHumanAI = () => {
|
||||||
const Icon = item.icon;
|
const Icon = item.icon;
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
key={index}
|
key={item.id}
|
||||||
initial={{ opacity: 0, scale: 0.9 }}
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
whileInView={{ opacity: 1, scale: 1 }}
|
whileInView={{ opacity: 1, scale: 1 }}
|
||||||
viewport={{ once: true }}
|
viewport={{ once: true }}
|
||||||
|
|
@ -42,7 +44,7 @@ const WhyHumanAI = () => {
|
||||||
<div className="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center text-secondary mb-6 group-hover:bg-secondary/20 transition-colors">
|
<div className="w-12 h-12 rounded-full bg-secondary/10 flex items-center justify-center text-secondary mb-6 group-hover:bg-secondary/20 transition-colors">
|
||||||
<Icon size={24} />
|
<Icon size={24} />
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-semibold text-lg">{item.title}</h3>
|
<h3 className="font-semibold text-lg">{t.why.items[item.id]}</h3>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -8,76 +8,39 @@ import {
|
||||||
ShieldCheck,
|
ShieldCheck,
|
||||||
BarChart3,
|
BarChart3,
|
||||||
Layout,
|
Layout,
|
||||||
MessageSquare,
|
|
||||||
Eye,
|
Eye,
|
||||||
Settings,
|
Settings,
|
||||||
Rocket
|
Rocket,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
// Structure only — no copy. Icons are React components and cannot live in the
|
||||||
|
// dictionaries without pulling React into them, and ids/hrefs are not
|
||||||
|
// translatable anyway. The matching text lives in i18n under the same id, so
|
||||||
|
// order and cardinality are defined once here rather than duplicated per
|
||||||
|
// language.
|
||||||
|
|
||||||
export const offerings = [
|
export const offerings = [
|
||||||
{
|
{ id: 'strategy', icon: Search },
|
||||||
id: 'strategy',
|
{ id: 'automation', icon: Workflow },
|
||||||
title: 'AI Strategy & Advisory',
|
{ id: 'products', icon: Layout },
|
||||||
description: 'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
|
// Deep-link to the dedicated product page; the label is translated.
|
||||||
points: ['audyt procesów', 'mapa use case’ów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
|
{ id: 'multiagent', icon: Cpu, link: { href: '/platforma' } },
|
||||||
icon: Search
|
] as const;
|
||||||
},
|
export type OfferingId = (typeof offerings)[number]['id'];
|
||||||
{
|
|
||||||
id: 'automation',
|
|
||||||
title: 'AI Automation & Workflows',
|
|
||||||
description: 'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
|
|
||||||
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
|
|
||||||
icon: Workflow
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'products',
|
|
||||||
title: 'AI Products & Interfaces',
|
|
||||||
description: 'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
|
|
||||||
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
|
|
||||||
icon: Layout
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'multiagent',
|
|
||||||
title: 'Multiagent Systems & Infrastructure',
|
|
||||||
description: 'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
|
|
||||||
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
|
|
||||||
icon: Cpu,
|
|
||||||
// Deep-link to the dedicated product page (/platforma).
|
|
||||||
link: { label: 'Zobacz jak to działa', href: '/platforma' }
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const whyHumanAI = [
|
export const whyHumanAI = [
|
||||||
{
|
{ id: 'hitl', icon: Users },
|
||||||
title: 'Human-in-the-loop',
|
{ id: 'security', icon: ShieldCheck },
|
||||||
icon: Users
|
{ id: 'integration', icon: Layers },
|
||||||
},
|
{ id: 'impact', icon: BarChart3 },
|
||||||
{
|
] as const;
|
||||||
title: 'Bezpieczeństwo od początku',
|
export type WhyId = (typeof whyHumanAI)[number]['id'];
|
||||||
icon: ShieldCheck
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Integracja z istniejącymi narzędziami',
|
|
||||||
icon: Layers
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Mierzalny efekt biznesowy',
|
|
||||||
icon: BarChart3
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
export const processSteps = [
|
export const processSteps = [
|
||||||
{ id: 1, title: 'Diagnoza', icon: Eye },
|
{ id: 'diagnosis', number: 1, icon: Eye },
|
||||||
{ id: 2, title: 'Projekt rozwiązania', icon: Layout },
|
{ id: 'design', number: 2, icon: Layout },
|
||||||
{ id: 3, title: 'Prototyp', icon: Zap },
|
{ id: 'prototype', number: 3, icon: Zap },
|
||||||
{ id: 4, title: 'Wdrożenie', icon: Rocket },
|
{ id: 'deployment', number: 4, icon: Rocket },
|
||||||
{ id: 5, title: 'Utrzymanie i rozwój', icon: Settings }
|
{ id: 'maintenance', number: 5, icon: Settings },
|
||||||
];
|
] as const;
|
||||||
|
export type StepId = (typeof processSteps)[number]['id'];
|
||||||
export const audience = [
|
|
||||||
'founderzy i małe zespoły',
|
|
||||||
'firmy usługowe',
|
|
||||||
'działy operacyjne',
|
|
||||||
'zespoły produktowe',
|
|
||||||
'software house’y i integratorzy'
|
|
||||||
];
|
|
||||||
|
|
|
||||||
254
src/i18n/en.ts
254
src/i18n/en.ts
|
|
@ -1,4 +1,122 @@
|
||||||
export const en = {
|
import type { Bullet, Rich } from './types';
|
||||||
|
import type { pl } from './pl';
|
||||||
|
|
||||||
|
// Step 1 of the i18n rollout: the keys are in place, the values are still the
|
||||||
|
// Polish source text. Translating them is the next commit — this file's diff is
|
||||||
|
// then purely textual and reviewable sentence by sentence.
|
||||||
|
|
||||||
|
export const en: typeof pl = {
|
||||||
|
nav: {
|
||||||
|
offerings: 'Oferta',
|
||||||
|
platform: 'Platforma',
|
||||||
|
process: 'Proces',
|
||||||
|
contact: 'Kontakt',
|
||||||
|
cta: 'Porozmawiajmy',
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
backToHome: '← Back to homepage',
|
||||||
|
},
|
||||||
|
hero: {
|
||||||
|
// Split so the accent span can wrap a different phrase per language.
|
||||||
|
titleBefore: 'Budujemy ',
|
||||||
|
titleAccent: 'ludzką stronę',
|
||||||
|
titleAfter: ' AI',
|
||||||
|
subtitle:
|
||||||
|
'Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej — od automatyzacji po multiagentowe platformy produktowe.',
|
||||||
|
ctaPrimary: 'Zacznijmy od audytu AI',
|
||||||
|
ctaSecondary: 'Zobacz ofertę',
|
||||||
|
},
|
||||||
|
about: {
|
||||||
|
title: 'Czym jest humanAI?',
|
||||||
|
lead: 'humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe. Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.',
|
||||||
|
points: [
|
||||||
|
'Strategia bez hype’u',
|
||||||
|
'Automatyzacje, które da się utrzymać',
|
||||||
|
'Agenci pod kontrolą człowieka',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
offerings: {
|
||||||
|
title: 'Nasza Oferta',
|
||||||
|
lead: 'Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.',
|
||||||
|
// Service names stay identical across languages, but are kept as per-language
|
||||||
|
// keys so they can diverge later without a refactor.
|
||||||
|
items: {
|
||||||
|
strategy: {
|
||||||
|
title: 'AI Strategy & Advisory',
|
||||||
|
description:
|
||||||
|
'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
|
||||||
|
points: ['audyt procesów', 'mapa use case’ów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
|
||||||
|
},
|
||||||
|
automation: {
|
||||||
|
title: 'AI Automation & Workflows',
|
||||||
|
description:
|
||||||
|
'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
|
||||||
|
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
title: 'AI Products & Interfaces',
|
||||||
|
description:
|
||||||
|
'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
|
||||||
|
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
|
||||||
|
},
|
||||||
|
multiagent: {
|
||||||
|
title: 'Multiagent Systems & Infrastructure',
|
||||||
|
description:
|
||||||
|
'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
|
||||||
|
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
|
||||||
|
linkLabel: 'Zobacz jak to działa',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
why: {
|
||||||
|
title: 'AI nie powinno być czarną skrzynką',
|
||||||
|
lead: 'Najlepsze wdrożenia AI są zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy, które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.',
|
||||||
|
items: {
|
||||||
|
hitl: 'Human-in-the-loop',
|
||||||
|
security: 'Bezpieczeństwo od początku',
|
||||||
|
integration: 'Integracja z istniejącymi narzędziami',
|
||||||
|
impact: 'Mierzalny efekt biznesowy',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process: {
|
||||||
|
title: 'Od pomysłu do działającego systemu',
|
||||||
|
stepLabel: 'Krok',
|
||||||
|
steps: {
|
||||||
|
diagnosis: 'Diagnoza',
|
||||||
|
design: 'Projekt rozwiązania',
|
||||||
|
prototype: 'Prototyp',
|
||||||
|
deployment: 'Wdrożenie',
|
||||||
|
maintenance: 'Utrzymanie i rozwój',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
audience: {
|
||||||
|
title: 'Dla kogo',
|
||||||
|
items: [
|
||||||
|
'founderzy i małe zespoły',
|
||||||
|
'firmy usługowe',
|
||||||
|
'działy operacyjne',
|
||||||
|
'zespoły produktowe',
|
||||||
|
'software house’y i integratorzy',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
cta: {
|
||||||
|
title: 'Masz proces, który powinien już pracować sam?',
|
||||||
|
lead: 'Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.',
|
||||||
|
quote: '"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
tagline: 'ludzka strona AI — budujemy praktyczne systemy AI dla ludzi i organizacji.',
|
||||||
|
navHeading: 'Nawigacja',
|
||||||
|
privacyHeading: 'Prywatność',
|
||||||
|
privacyPolicy: 'Polityka prywatności',
|
||||||
|
cookies: 'Cookies',
|
||||||
|
rights: 'Wszelkie prawa zastrzeżone.',
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'humanAI — ludzka strona AI',
|
||||||
|
description:
|
||||||
|
'Strategia, automatyzacje, produkty AI i systemy multiagentowe projektowane z człowiekiem w centrum.',
|
||||||
|
},
|
||||||
contact: {
|
contact: {
|
||||||
labelName: 'Name',
|
labelName: 'Name',
|
||||||
placeholderName: 'Your name',
|
placeholderName: 'Your name',
|
||||||
|
|
@ -25,7 +143,6 @@ export const en = {
|
||||||
title: 'Privacy Policy',
|
title: 'Privacy Policy',
|
||||||
lastUpdated: 'Last updated: June 2026',
|
lastUpdated: 'Last updated: June 2026',
|
||||||
intro: 'This privacy policy describes how humanAI (gethumanai.pl) processes personal data and protects the privacy of its users.',
|
intro: 'This privacy policy describes how humanAI (gethumanai.pl) processes personal data and protects the privacy of its users.',
|
||||||
backToHome: '← Back to homepage',
|
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
title: '1. Data Controller',
|
title: '1. Data Controller',
|
||||||
|
|
@ -53,4 +170,137 @@ export const en = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
platform: {
|
||||||
|
title: 'Nadzór nad systemami agentowymi',
|
||||||
|
workingName: '(nazwa robocza — do potwierdzenia przed publikacją)',
|
||||||
|
watchers: {
|
||||||
|
title: 'Kto pilnuje agentów, którzy pilnują wszystkiego innego?',
|
||||||
|
paragraphs: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
t: 'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który ',
|
||||||
|
},
|
||||||
|
{ t: 'obserwuje inne systemy — w tym inne systemy agentowe', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.',
|
||||||
|
] as Rich[],
|
||||||
|
},
|
||||||
|
problem: {
|
||||||
|
title: 'Problem, który znika',
|
||||||
|
bullets: [
|
||||||
|
{
|
||||||
|
lead: 'Autonomia bez ram to ryzyko.',
|
||||||
|
body: ' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lead: 'Automatyka to nie inteligencja.',
|
||||||
|
body: [
|
||||||
|
{ t: ' Wiele domów i firm ma już systemy, które ' },
|
||||||
|
{ t: 'wykonują', em: 'em' },
|
||||||
|
{ t: ' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie ' },
|
||||||
|
{ t: 'rozumie', em: 'em' },
|
||||||
|
{ t: ': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lead: 'Wiedza znika.',
|
||||||
|
body: ' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
howItWorks: {
|
||||||
|
title: 'Jak to działa',
|
||||||
|
core: [
|
||||||
|
{ t: 'Rdzeń nadzoru — jeden, wspólny dla wszystkiego.', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
humanAsk: [
|
||||||
|
{
|
||||||
|
t: 'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: ',
|
||||||
|
},
|
||||||
|
{ t: '„Nie zamknąłeś rolet. Zamknąć teraz?"', em: 'quote' },
|
||||||
|
{
|
||||||
|
t: ' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
tailored: [
|
||||||
|
{ t: 'System roboczy — budowany pod Ciebie.', em: 'strong' },
|
||||||
|
{ t: ' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.' },
|
||||||
|
] as Rich,
|
||||||
|
home: {
|
||||||
|
title: 'Dla domu',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
t: 'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która ',
|
||||||
|
},
|
||||||
|
{ t: 'rozumie kontekst', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
},
|
||||||
|
business: {
|
||||||
|
title: 'Dla firm',
|
||||||
|
body: 'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.' as Rich,
|
||||||
|
},
|
||||||
|
shared:
|
||||||
|
'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.' as Rich,
|
||||||
|
},
|
||||||
|
underTheHood: {
|
||||||
|
title: 'Pod maską — dla ciekawych',
|
||||||
|
bullets: [
|
||||||
|
{
|
||||||
|
body: [
|
||||||
|
{ t: 'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje ' },
|
||||||
|
{ t: 'czytelna, kompilowana wiki utrzymywana przez model językowy', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
why: {
|
||||||
|
title: 'Dlaczego to, a nie zwykły monitoring czy zwykła automatyka',
|
||||||
|
bullets: [
|
||||||
|
{ lead: 'Rozumiemy kontekst, nie tylko wykonujemy polecenia.' },
|
||||||
|
{ lead: 'Naprawiamy, nie tylko alarmujemy.' },
|
||||||
|
{
|
||||||
|
lead: 'Człowiek naprawdę jest w pętli',
|
||||||
|
body: ' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.',
|
||||||
|
},
|
||||||
|
{ lead: 'Zero czarnej skrzynki.', body: ' Każda decyzja zostawia ślad, który można później przejrzeć.' },
|
||||||
|
{
|
||||||
|
lead: 'Twoje dane zostają Twoje',
|
||||||
|
body: ' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
title: 'Uczciwie o tym, gdzie jesteśmy',
|
||||||
|
paragraphs: [
|
||||||
|
'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.',
|
||||||
|
'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.',
|
||||||
|
] as Rich[],
|
||||||
|
},
|
||||||
|
cta: {
|
||||||
|
title: 'Umów rozmowę',
|
||||||
|
body: 'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.' as Rich,
|
||||||
|
button: 'Porozmawiajmy',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
247
src/i18n/pl.ts
247
src/i18n/pl.ts
|
|
@ -1,4 +1,117 @@
|
||||||
|
import type { Bullet, Rich } from './types';
|
||||||
|
|
||||||
export const pl = {
|
export const pl = {
|
||||||
|
nav: {
|
||||||
|
offerings: 'Oferta',
|
||||||
|
platform: 'Platforma',
|
||||||
|
process: 'Proces',
|
||||||
|
contact: 'Kontakt',
|
||||||
|
cta: 'Porozmawiajmy',
|
||||||
|
},
|
||||||
|
common: {
|
||||||
|
backToHome: '← Wróć na stronę główną',
|
||||||
|
},
|
||||||
|
hero: {
|
||||||
|
// Split so the accent span can wrap a different phrase per language.
|
||||||
|
titleBefore: 'Budujemy ',
|
||||||
|
titleAccent: 'ludzką stronę',
|
||||||
|
titleAfter: ' AI',
|
||||||
|
subtitle:
|
||||||
|
'Projektujemy i wdrażamy systemy AI, które pomagają ludziom pracować szybciej, mądrzej i spokojniej — od automatyzacji po multiagentowe platformy produktowe.',
|
||||||
|
ctaPrimary: 'Zacznijmy od audytu AI',
|
||||||
|
ctaSecondary: 'Zobacz ofertę',
|
||||||
|
},
|
||||||
|
about: {
|
||||||
|
title: 'Czym jest humanAI?',
|
||||||
|
lead: 'humanAI łączy doradztwo, automatyzację, budowę produktów i własne środowisko agentowe. Pomagamy przejść od ciekawości wokół AI do działających procesów, narzędzi i systemów.',
|
||||||
|
points: [
|
||||||
|
'Strategia bez hype’u',
|
||||||
|
'Automatyzacje, które da się utrzymać',
|
||||||
|
'Agenci pod kontrolą człowieka',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
offerings: {
|
||||||
|
title: 'Nasza Oferta',
|
||||||
|
lead: 'Budujemy kompleksowe rozwiązania, które przekładają potencjał sztucznej inteligencji na realne wyniki biznesowe.',
|
||||||
|
// Service names stay identical across languages, but are kept as per-language
|
||||||
|
// keys so they can diverge later without a refactor.
|
||||||
|
items: {
|
||||||
|
strategy: {
|
||||||
|
title: 'AI Strategy & Advisory',
|
||||||
|
description:
|
||||||
|
'Pomagamy znaleźć realne zastosowania AI w firmie, wybrać priorytety i zaplanować wdrożenia bez przepalania czasu na przypadkowe eksperymenty.',
|
||||||
|
points: ['audyt procesów', 'mapa use case’ów', 'priorytetyzacja wdrożeń', 'polityki bezpieczeństwa AI'],
|
||||||
|
},
|
||||||
|
automation: {
|
||||||
|
title: 'AI Automation & Workflows',
|
||||||
|
description:
|
||||||
|
'Budujemy automatyzacje, które łączą modele AI z codziennymi narzędziami: dokumentami, mailem, CRM, bazami danych, API i wewnętrznymi procesami.',
|
||||||
|
points: ['automatyzacje operacyjne', 'integracje API', 'workflow z człowiekiem w pętli', 'monitoring i logi'],
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
title: 'AI Products & Interfaces',
|
||||||
|
description:
|
||||||
|
'Projektujemy i tworzymy aplikacje, panele, chatboty, copilots i wyszukiwarki semantyczne, które przekładają AI na użyteczne doświadczenie użytkownika.',
|
||||||
|
points: ['aplikacje webowe', 'panele AI', 'chatboty i copilots', 'RAG / wyszukiwanie w wiedzy'],
|
||||||
|
},
|
||||||
|
multiagent: {
|
||||||
|
title: 'Multiagent Systems & Infrastructure',
|
||||||
|
description:
|
||||||
|
'Tworzymy systemy wieloagentowe, które potrafią planować, wykonywać zadania, korzystać z narzędzi i współpracować z człowiekiem przy zachowaniu kontroli i audytowalności.',
|
||||||
|
points: ['agent orchestration', 'tool registry / MCP', 'approval gates', 'pamięć, logi i obserwowalność'],
|
||||||
|
linkLabel: 'Zobacz jak to działa',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
why: {
|
||||||
|
title: 'AI nie powinno być czarną skrzynką',
|
||||||
|
lead: 'Najlepsze wdrożenia AI są zrozumiałe, mierzalne i bezpieczne. Dlatego projektujemy systemy, które pokazują swoje działanie, zostawiają ślad decyzyjny i pozwalają człowiekowi zatwierdzać ważne kroki.',
|
||||||
|
items: {
|
||||||
|
hitl: 'Human-in-the-loop',
|
||||||
|
security: 'Bezpieczeństwo od początku',
|
||||||
|
integration: 'Integracja z istniejącymi narzędziami',
|
||||||
|
impact: 'Mierzalny efekt biznesowy',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
process: {
|
||||||
|
title: 'Od pomysłu do działającego systemu',
|
||||||
|
stepLabel: 'Krok',
|
||||||
|
steps: {
|
||||||
|
diagnosis: 'Diagnoza',
|
||||||
|
design: 'Projekt rozwiązania',
|
||||||
|
prototype: 'Prototyp',
|
||||||
|
deployment: 'Wdrożenie',
|
||||||
|
maintenance: 'Utrzymanie i rozwój',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
audience: {
|
||||||
|
title: 'Dla kogo',
|
||||||
|
items: [
|
||||||
|
'founderzy i małe zespoły',
|
||||||
|
'firmy usługowe',
|
||||||
|
'działy operacyjne',
|
||||||
|
'zespoły produktowe',
|
||||||
|
'software house’y i integratorzy',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
cta: {
|
||||||
|
title: 'Masz proces, który powinien już pracować sam?',
|
||||||
|
lead: 'Opowiedz, co robisz ręcznie, powtarzalnie albo zbyt wolno. Sprawdzimy, czy AI może to uprościć.',
|
||||||
|
quote: '"Na start wystarczy jeden proces, jeden problem albo jeden pomysł."',
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
tagline: 'ludzka strona AI — budujemy praktyczne systemy AI dla ludzi i organizacji.',
|
||||||
|
navHeading: 'Nawigacja',
|
||||||
|
privacyHeading: 'Prywatność',
|
||||||
|
privacyPolicy: 'Polityka prywatności',
|
||||||
|
cookies: 'Cookies',
|
||||||
|
rights: 'Wszelkie prawa zastrzeżone.',
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
title: 'humanAI — ludzka strona AI',
|
||||||
|
description:
|
||||||
|
'Strategia, automatyzacje, produkty AI i systemy multiagentowe projektowane z człowiekiem w centrum.',
|
||||||
|
},
|
||||||
contact: {
|
contact: {
|
||||||
labelName: 'Imię',
|
labelName: 'Imię',
|
||||||
placeholderName: 'Twoje imię',
|
placeholderName: 'Twoje imię',
|
||||||
|
|
@ -25,7 +138,6 @@ export const pl = {
|
||||||
title: 'Polityka prywatności',
|
title: 'Polityka prywatności',
|
||||||
lastUpdated: 'Ostatnia aktualizacja: czerwiec 2026',
|
lastUpdated: 'Ostatnia aktualizacja: czerwiec 2026',
|
||||||
intro: 'Niniejsza polityka prywatności opisuje, w jaki sposób humanAI (gethumanai.pl) przetwarza dane osobowe i dba o prywatność użytkowników.',
|
intro: 'Niniejsza polityka prywatności opisuje, w jaki sposób humanAI (gethumanai.pl) przetwarza dane osobowe i dba o prywatność użytkowników.',
|
||||||
backToHome: '← Wróć na stronę główną',
|
|
||||||
sections: [
|
sections: [
|
||||||
{
|
{
|
||||||
title: '1. Administrator danych',
|
title: '1. Administrator danych',
|
||||||
|
|
@ -53,4 +165,137 @@ export const pl = {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
platform: {
|
||||||
|
title: 'Nadzór nad systemami agentowymi',
|
||||||
|
workingName: '(nazwa robocza — do potwierdzenia przed publikacją)',
|
||||||
|
watchers: {
|
||||||
|
title: 'Kto pilnuje agentów, którzy pilnują wszystkiego innego?',
|
||||||
|
paragraphs: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
t: 'Automatyzacje i agenci AI potrafią pracować bez człowieka — porządkować dokumenty, sterować urządzeniami, reagować na zdarzenia. Ale zostawione bez nadzoru, prędzej czy później zrobią coś, czego nikt nie chciał. Zbudowaliśmy system, który ',
|
||||||
|
},
|
||||||
|
{ t: 'obserwuje inne systemy — w tym inne systemy agentowe', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' — wykrywa, że coś nie działa, diagnozuje przyczynę i naprawia problem sam. A tam, gdzie decyzja jest nieodwracalna, czeka na człowieka.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'To nie koncept. Ten sam rdzeń od miesięcy prowadzi naszą własną, rozproszoną infrastrukturę — i przeszedł przez realne awarie, z których każda coś go nauczyła.',
|
||||||
|
] as Rich[],
|
||||||
|
},
|
||||||
|
problem: {
|
||||||
|
title: 'Problem, który znika',
|
||||||
|
bullets: [
|
||||||
|
{
|
||||||
|
lead: 'Autonomia bez ram to ryzyko.',
|
||||||
|
body: ' Coś, co może samo otworzyć bramę albo zmienić konfigurację usługi, potrzebuje jasnej granicy: co wolno zrobić samodzielnie, co wymaga zgody człowieka.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lead: 'Automatyka to nie inteligencja.',
|
||||||
|
body: [
|
||||||
|
{ t: ' Wiele domów i firm ma już systemy, które ' },
|
||||||
|
{ t: 'wykonują', em: 'em' },
|
||||||
|
{ t: ' polecenia — światła, rolety, bramy, obieg dokumentów. Problem w tym, że nic tego nie ' },
|
||||||
|
{ t: 'rozumie', em: 'em' },
|
||||||
|
{ t: ': nie kojarzy faktów, nie reaguje na kontekst, nie uczy się.' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lead: 'Wiedza znika.',
|
||||||
|
body: ' Dlaczego coś się zepsuło miesiąc temu i co wtedy pomogło? Zwykle ta wiedza siedzi w głowie jednej osoby albo w nieprzeszukiwalnym stosie dokumentów.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
howItWorks: {
|
||||||
|
title: 'Jak to działa',
|
||||||
|
core: [
|
||||||
|
{ t: 'Rdzeń nadzoru — jeden, wspólny dla wszystkiego.', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' Lekki agent na każdej maszynie zgłasza stan usług. Centralny „mózg" buduje z tego pełny obraz sytuacji, wykrywa odchylenia od tego, co powinno działać, i albo naprawia problem sam — jeśli akcja jest bezpieczna — albo pyta człowieka, jeśli nie jest.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
humanAsk: [
|
||||||
|
{
|
||||||
|
t: 'To „pytanie człowieka" nie jest teorią. Przykład z życia: system zauważa, że wyjechałeś na weekend, a rolety zostały otwarte. Sam ich nie zamknie — wysyła Ci wiadomość: ',
|
||||||
|
},
|
||||||
|
{ t: '„Nie zamknąłeś rolet. Zamknąć teraz?"', em: 'quote' },
|
||||||
|
{
|
||||||
|
t: ' Odpisujesz „tak" — i dopiero wtedy system zleca to istniejącej automatyce domowej. Decyzja zawsze należy do Ciebie; wykonanie bierze na siebie system.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
tailored: [
|
||||||
|
{ t: 'System roboczy — budowany pod Ciebie.', em: 'strong' },
|
||||||
|
{ t: ' To, co ten nadzór pilnuje, dopasowujemy do konkretnej potrzeby.' },
|
||||||
|
] as Rich,
|
||||||
|
home: {
|
||||||
|
title: 'Dla domu',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
t: 'Masz już zautomatyzowany dom — światła, rolety, bramy, klimatyzację — ale to automatyka, nie inteligencja: robi dokładnie to, co jej każesz, i nic więcej. Dokładamy warstwę, która ',
|
||||||
|
},
|
||||||
|
{ t: 'rozumie kontekst', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ': rozpoznaje Twój samochód po tablicy rejestracyjnej i otwiera bramę, zanim dojedziesz do niej. Widzi na kamerach, że nikogo nie ma w domu, i sama wygasza światła na noc. Zauważa, że wyjechałeś, a coś zostało otwarte — i pyta, zanim cokolwiek zrobi.',
|
||||||
|
},
|
||||||
|
] as Rich,
|
||||||
|
},
|
||||||
|
business: {
|
||||||
|
title: 'Dla firm',
|
||||||
|
body: 'Masz bałagan w dokumentach, obieg papierowy, który nikogo nie satysfakcjonuje, i dane rozsiane po cudzych chmurach, nad którymi nie masz pełnej kontroli. Budujemy Ci paperless na Twoich własnych serwerach — z własną domeną i autoryzacją, bez uzależnienia od zewnętrznych dostawców chmury. Indeksujemy dokumenty, zdjęcia i korespondencję tak, żeby dało się to przeszukać po sensie, nie po słowach kluczowych. Interfejs — webowy panel, a jeśli to naprawdę pasuje do Twojej firmy, także chatbot — dobieramy do tego, czego faktycznie potrzebujesz, a nie do tego, co akurat modne.' as Rich,
|
||||||
|
},
|
||||||
|
shared:
|
||||||
|
'Obie ścieżki łączy to samo: cała konfiguracja tego, co ma działać, jest zapisana jako kod w repozytorium — każda zmiana ma historię i da się ją cofnąć — i obie działają pod tym samym nadzorem, który pilnuje, żeby nic nie zawiodło po cichu.' as Rich,
|
||||||
|
},
|
||||||
|
underTheHood: {
|
||||||
|
title: 'Pod maską — dla ciekawych',
|
||||||
|
bullets: [
|
||||||
|
{
|
||||||
|
body: [
|
||||||
|
{ t: 'Baza wiedzy nie kończy jako martwy indeks. Nad wyszukiwaniem semantycznym powstaje ' },
|
||||||
|
{ t: 'czytelna, kompilowana wiki utrzymywana przez model językowy', em: 'strong' },
|
||||||
|
{
|
||||||
|
t: ' — pliki tekstowe z linkami między pojęciami, które agent czyta i aktualizuje tak jak człowiek utrzymuje kod. Budujemy to na otwartym standardzie (Google OKF), nie na własnym, zamkniętym formacie — żeby wiedza, którą zbudujemy, zawsze zostawała czytelna i przenośna.',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'Do zapytań najpierw sięga tańszy model — droższy dopiero wtedy, gdy sprawa naprawdę tego wymaga. W praktyce: streszczenie całego korpusu dokumentów potrafiło kosztować grosze zamiast dni obliczeń.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'Nie wszystko musi być online 24 godziny na dobę. Kiedy główna maszyna śpi, zapytania automatycznie przejmuje zapasowy sprzęt — bez przerwy zauważalnej dla użytkownika.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
body: 'System sam odróżnia „usługa nie działa" od „usługa śpi zgodnie z planem" — co wcześniej było częstym źródłem fałszywych alarmów.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
why: {
|
||||||
|
title: 'Dlaczego to, a nie zwykły monitoring czy zwykła automatyka',
|
||||||
|
bullets: [
|
||||||
|
{ lead: 'Rozumiemy kontekst, nie tylko wykonujemy polecenia.' },
|
||||||
|
{ lead: 'Naprawiamy, nie tylko alarmujemy.' },
|
||||||
|
{
|
||||||
|
lead: 'Człowiek naprawdę jest w pętli',
|
||||||
|
body: ' — decyzje zawsze do Ciebie, wykonanie bierze na siebie system.',
|
||||||
|
},
|
||||||
|
{ lead: 'Zero czarnej skrzynki.', body: ' Każda decyzja zostawia ślad, który można później przejrzeć.' },
|
||||||
|
{
|
||||||
|
lead: 'Twoje dane zostają Twoje',
|
||||||
|
body: ' — własny serwer, własna domena, bez uzależnienia od cudzej chmury.',
|
||||||
|
},
|
||||||
|
] as Bullet[],
|
||||||
|
},
|
||||||
|
status: {
|
||||||
|
title: 'Uczciwie o tym, gdzie jesteśmy',
|
||||||
|
paragraphs: [
|
||||||
|
'Rdzeń nadzoru prowadzi naszą infrastrukturę na co dzień — samonaprawa działa od początku do końca, alerty trafiają na telefon, baza wiedzy odpowiada na pytania nawet gdy główny sprzęt śpi.',
|
||||||
|
'Dedykowane wdrożenia — pod konkretny dom czy firmę — budujemy w miarę potrzeb, opierając się na tym samym, sprawdzonym rdzeniu. Wolimy powiedzieć wprost, co jeszcze dopracowujemy, niż obiecywać więcej niż działa.',
|
||||||
|
] as Rich[],
|
||||||
|
},
|
||||||
|
cta: {
|
||||||
|
title: 'Umów rozmowę',
|
||||||
|
body: 'Powiedz, co chcesz zautomatyzować albo uporządkować — zobaczymy, jak to zbudować i objąć nadzorem, który sami na sobie testujemy.' as Rich,
|
||||||
|
button: 'Porozmawiajmy',
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
17
src/i18n/types.ts
Normal file
17
src/i18n/types.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
/**
|
||||||
|
* Shapes for copy that carries inline emphasis. Text with <strong>/<em> inside a
|
||||||
|
* sentence cannot be one flat string without either splitting the component or
|
||||||
|
* injecting HTML — so it is stored as a list of runs and rendered by <RichText>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type Run = {
|
||||||
|
t: string;
|
||||||
|
/** 'quote' is an <em> that brightens to full foreground — used for quoted speech. */
|
||||||
|
em?: 'strong' | 'em' | 'quote';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Plain text, or a run list when the sentence needs inline emphasis. */
|
||||||
|
export type Rich = string | Run[];
|
||||||
|
|
||||||
|
/** List item rendered as an optional bold lead-in followed by the rest. */
|
||||||
|
export type Bullet = { lead?: string; body?: Rich };
|
||||||
Loading…
Reference in a new issue