translation added

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-04-01 10:53:42 +05:00
parent 80343c9ca8
commit 6041e6a719
15 changed files with 650 additions and 130 deletions

View File

@@ -9,6 +9,7 @@ import DocIllustration from './DocIllustration';
import Section from './Section';
import Stat from './Stat';
import StartButton from './StartButton';
import { useTranslations } from 'next-intl';
interface HeroProps {
onStart: () => void;
@@ -17,6 +18,23 @@ interface HeroProps {
const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
const isMobile = useIsMobile();
const t = useTranslations('Hero');
const tStats = useTranslations('Stats');
const getTranslatedLabel = (label: string) => {
switch (label) {
case 'Detection accuracy':
return tStats('accuracy');
case 'Documents checked':
return tStats('documents');
case 'Supported formats':
return tStats('formats');
case 'Report turnaround':
return tStats('turnaround');
default:
return label;
}
};
return (
<div style={{ position: 'relative', overflow: 'hidden', background: C.bg }}>
@@ -71,7 +89,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
>
{/* Text block */}
<div style={{ maxWidth: 600, flex: 1 }}>
<Badge>Academic Integrity Platform</Badge>
<Badge>{t('badge')}</Badge>
<motion.div variants={stagger} initial="hidden" animate="visible">
<motion.h1
@@ -86,7 +104,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
marginBottom: 4,
}}
>
Is Your Work
{t('mainHeading')}
</motion.h1>
<motion.h1
variants={fadeUp(0.1)}
@@ -101,7 +119,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
marginBottom: 28,
}}
>
Truly Original?
{t('mainHeadingItalic')}
</motion.h1>
</motion.div>
@@ -117,10 +135,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
marginBottom: 40,
}}
>
Plagiarism is presenting someone else&lsquo;s ideas or words as
your own. In academia and professional life, it carries serious
consequences. Our platform detects it in seconds so you can
submit with full confidence.
{t('description')}
</motion.p>
<motion.div
@@ -142,7 +157,7 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
fontFamily: "'DM Mono', monospace",
}}
>
Certificate issued within 24h
{t('certificateNote')}
</span>
</motion.div>
</div>
@@ -165,9 +180,15 @@ const Hero: FC<HeroProps> = ({ onStart, blobY }) => {
borderTop: `1px solid ${C.border}`,
}}
>
{STATS.map((s) => (
<Stat key={s.label} value={s.value} label={s.label} />
))}
{STATS.map((s) => {
return (
<Stat
key={s.label}
value={s.value}
label={getTranslatedLabel(s.label)}
/>
);
})}
</motion.div>
</Section>
</div>

View File

@@ -5,51 +5,82 @@ import { C } from '../tokens';
import { INFO_CARDS } from '../constants';
import InfoCard from './InfoCard';
import Section from './Section';
import { useTranslations } from 'next-intl';
const InfoSection: FC = () => (
<div style={{ background: C.surfaceWarm }}>
<Section style={{ paddingTop: 96, paddingBottom: 96 }}>
{/* Heading */}
<motion.div
variants={fadeUp()}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
style={{ marginBottom: 48 }}
>
<p
style={{
fontFamily: "'DM Mono', monospace",
fontSize: 11,
color: C.accent,
letterSpacing: '0.14em',
textTransform: 'uppercase',
marginBottom: 10,
}}
>
Why It Matters
</p>
<h2
style={{
fontFamily: "'Playfair Display', serif",
fontSize: 'clamp(26px, 3.5vw, 40px)',
fontWeight: 700,
color: C.text,
lineHeight: 1.2,
}}
>
Understanding Plagiarism
</h2>
</motion.div>
const InfoSection: FC = () => {
const t = useTranslations('InfoSection');
const tCards = useTranslations('InfoCards');
{/* Cards */}
<div style={{ display: 'flex', gap: 20, flexWrap: 'wrap' }}>
{INFO_CARDS.map((card) => (
<InfoCard key={card.title} {...card} />
))}
</div>
</Section>
</div>
);
const getTranslatedCard = (card: (typeof INFO_CARDS)[0]) => {
switch (card.title) {
case 'What is Plagiarism?':
return {
...card,
title: tCards('card1Title'),
text: tCards('card1Desc'),
};
case 'Why Check Your Document?':
return {
...card,
title: tCards('card2Title'),
text: tCards('card2Desc'),
};
case 'What You Get':
return {
...card,
title: tCards('card3Title'),
text: tCards('card3Desc'),
};
default:
return card;
}
};
return (
<div style={{ background: C.surfaceWarm }}>
<Section style={{ paddingTop: 96, paddingBottom: 96 }}>
{/* Heading */}
<motion.div
variants={fadeUp()}
initial="hidden"
whileInView="visible"
viewport={{ once: true }}
style={{ marginBottom: 48 }}
>
<p
style={{
fontFamily: "'DM Mono', monospace",
fontSize: 11,
color: C.accent,
letterSpacing: '0.14em',
textTransform: 'uppercase',
marginBottom: 10,
}}
>
{t('label')}
</p>
<h2
style={{
fontFamily: "'Playfair Display', serif",
fontSize: 'clamp(26px, 3.5vw, 40px)',
fontWeight: 700,
color: C.text,
lineHeight: 1.2,
}}
>
{t('heading')}
</h2>
</motion.div>
{/* Cards */}
<div style={{ display: 'flex', gap: 20, flexWrap: 'wrap' }}>
{INFO_CARDS.map((card) => (
<InfoCard key={card.title} {...getTranslatedCard(card)} />
))}
</div>
</Section>
</div>
);
};
export default InfoSection;

View File

@@ -2,6 +2,7 @@
import { useState, type FC } from 'react';
import { motion } from 'framer-motion';
import { C } from '../tokens';
import { useTranslations } from 'next-intl';
interface StartButtonProps {
onClick: () => void;
@@ -10,6 +11,7 @@ interface StartButtonProps {
const StartButton: FC<StartButtonProps> = ({ onClick, small = false }) => {
const [hovered, setHovered] = useState(false);
const t = useTranslations('Common');
return (
<motion.button
@@ -35,7 +37,7 @@ const StartButton: FC<StartButtonProps> = ({ onClick, small = false }) => {
: `0 2px 8px ${C.accent}22`,
}}
>
Start Checking
{t('startButton')}
</motion.button>
);
};

View File

@@ -4,6 +4,7 @@ import { fadeUp } from '../animations';
import { C } from '../tokens';
import { STEPS } from '../constants';
import type { Step } from '../types';
import { useTranslations } from 'next-intl';
interface StepCardProps {
step: Step;
@@ -14,6 +15,45 @@ const StepCard: FC<StepCardProps> = ({ step, index }) => {
const ref = useRef<HTMLDivElement>(null);
const inView = useInView(ref, { once: true, margin: '-50px' });
const isLast = index === STEPS.length - 1;
const t = useTranslations('Steps');
const getStepTitle = (num: string) => {
switch (num) {
case '01':
return t('step1Title');
case '02':
return t('step2Title');
case '03':
return t('step3Title');
case '04':
return t('step4Title');
case '05':
return t('step5Title');
case '06':
return t('step6Title');
default:
return step.title;
}
};
const getStepDesc = (num: string) => {
switch (num) {
case '01':
return t('step1Desc');
case '02':
return t('step2Desc');
case '03':
return t('step3Desc');
case '04':
return t('step4Desc');
case '05':
return t('step5Desc');
case '06':
return t('step6Desc');
default:
return step.desc;
}
};
return (
<motion.div
@@ -87,7 +127,7 @@ const StepCard: FC<StepCardProps> = ({ step, index }) => {
fontWeight: 700,
}}
>
{step.title}
{getStepTitle(step.num)}
</h3>
</div>
<p
@@ -98,7 +138,7 @@ const StepCard: FC<StepCardProps> = ({ step, index }) => {
margin: 0,
}}
>
{step.desc}
{getStepDesc(step.num)}
</p>
</div>
</motion.div>

View File

@@ -7,6 +7,7 @@ import { useIsMobile } from '../hooks/useIsMobile';
import Section from './Section';
import StartButton from './StartButton';
import StepCard from './StepCard';
import { useTranslations } from 'next-intl';
interface StepsSectionProps {
stepsRef: React.RefObject<HTMLDivElement | null>;
@@ -15,6 +16,7 @@ interface StepsSectionProps {
const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
const isMobile = useIsMobile();
const t = useTranslations('StepsSection');
return (
<div
@@ -44,7 +46,7 @@ const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
marginBottom: 10,
}}
>
Process
{t('label')}
</p>
<h2
style={{
@@ -55,7 +57,7 @@ const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
lineHeight: 1.2,
}}
>
How It Works
{t('heading')}
</h2>
<p
style={{
@@ -65,7 +67,7 @@ const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
lineHeight: 1.75,
}}
>
Six simple steps from upload to certified report.
{t('description')}
</p>
</motion.div>
@@ -112,10 +114,10 @@ const StepsSection: FC<StepsSectionProps> = ({ stepsRef, onScrollTop }) => {
fontWeight: 700,
}}
>
Ready to verify your document?
{t('ctaHeading')}
</h3>
<p style={{ color: C.textMuted, fontSize: 13 }}>
Get your originality certificate in under 24 hours.
{t('ctaDescription')}
</p>
</div>
<StartButton onClick={onScrollTop} />

View File

@@ -2,10 +2,32 @@ import type { FC } from 'react';
import { motion } from 'framer-motion';
import { C } from '../tokens';
import { TICKER_ITEMS } from '../constants';
import { useTranslations } from 'next-intl';
const Ticker: FC = () => {
const t = useTranslations('Ticker');
const doubled = [...TICKER_ITEMS, ...TICKER_ITEMS];
const getTranslatedItem = (item: string, index: number) => {
const itemIndex = index % TICKER_ITEMS.length;
switch (itemIndex) {
case 0:
return t('item1');
case 1:
return t('item2');
case 2:
return t('item3');
case 3:
return t('item4');
case 4:
return t('item5');
case 5:
return t('item6');
default:
return item;
}
};
return (
<div
style={{
@@ -37,7 +59,7 @@ const Ticker: FC = () => {
color: i % 3 === 0 ? C.textMid : C.textMuted,
}}
>
{item}
{getTranslatedItem(item, i)}
<span style={{ marginLeft: 56, color: C.accent, opacity: 0.3 }}>
</span>