apply translations in all pages

This commit is contained in:
2026-04-17 11:13:20 +02:00
parent dbeb294920
commit 7a8022d11a
15 changed files with 108 additions and 124 deletions
+30 -28
View File
@@ -1,36 +1,38 @@
'use client';
import { useRef, useEffect, useState } from 'react';
const steps = [
{
title: 'Les Débuts',
text: "J'ai commencé par le web en 2019 suite à un stage, je n'ai plus jamais arrêté. Aujourd'hui je veux en faire mon métier.",
year: '2019',
position: 'top' as const,
left: '16%',
},
{
title: 'L\'Évolution',
text: "Après un bac STI2D avec mention Très bien j'ai entamé un BUT Informatique Parcours Développement IA.",
year: '2022',
position: 'bottom' as const,
left: '50%',
},
{
title: 'Aujourd\'hui',
text: "Je suis entrepreneur, co-fondateur d'une startup et développeur freelance, je vis de ma passion.",
year: '2026',
position: 'top' as const,
left: '84%',
},
];
const lineTop = '58%';
import { useTranslations } from "next-intl";
export default function TimelineSection() {
const sectionRef = useRef<HTMLElement>(null);
const [visible, setVisible] = useState(false);
const t = useTranslations('about');
const lineTop = '58%';
const steps = [
{
title: t('step1.title'),
text: t('step1.text'),
year: '2019',
position: 'top' as const,
left: '16%',
},
{
title: t('step2.title'),
text: t('step2.text'),
year: '2022',
position: 'bottom' as const,
left: '50%',
},
{
title: t('step3.title'),
text: t('step3.text'),
year: '2026',
position: 'top' as const,
left: '84%',
},
];
useEffect(() => {
const section = sectionRef.current;
@@ -56,11 +58,11 @@ export default function TimelineSection() {
{/* Label */}
<div className="reveal flex items-center gap-3 mb-6">
<span className="w-8 h-px bg-brand-brown/40" />
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">Parcours</span>
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">{t('sectionLabel')}</span>
</div>
<h2 className="reveal font-serif text-[clamp(48px,7vw,100px)] leading-none text-brand-brown mb-16 md:mb-24">
À propos
{t('title')}
</h2>
{/* Mobile layout */}
@@ -1,28 +1,29 @@
'use client';
import { useRef, useEffect } from 'react';
import { FeatureColumn } from '@/components/ui/FeatureColumn';
import { useTranslations } from "next-intl";
const features = [
{
imagePath: '/icons/brain.svg',
title: 'Plus qu\'un simple exécutant',
text: 'Grâce à mon background en conception numérique et mobile, je ne me contente pas de coder. J\'apporte un regard critique et constructif sur l\'ensemble de votre projet.',
},
{
imagePath: '/icons/building.svg',
title: 'Des fondations en béton',
text: 'Ma spécialité : l\'architecture. Je construis des solutions pérennes, évolutives et capables d\'absorber la croissance de votre produit dans le temps.',
},
{
imagePath: '/icons/people.svg',
title: 'L\'utilisateur au centre',
text: 'Le code parfait n\'est rien si le produit ne répond pas à un besoin. Je place l\'expérience utilisateur et la fonctionnalité au cœur de mes développements.',
},
];
export default function FeatureSection() {
export default function ApproachSection() {
const sectionRef = useRef<HTMLElement>(null);
const t = useTranslations('approach');
const features = [
{
imagePath: '/icons/brain.svg',
title: t('feature1.title'),
text: t('feature1.text'),
},
{
imagePath: '/icons/building.svg',
title: t('feature2.title'),
text: t('feature2.text'),
},
{
imagePath: '/icons/people.svg',
title: t('feature3.title'),
text: t('feature3.text'),
},
];
useEffect(() => {
const section = sectionRef.current;
@@ -51,7 +52,7 @@ export default function FeatureSection() {
{/* Section label */}
<div className="reveal flex items-center gap-3 mb-12 md:mb-16">
<span className="w-8 h-px bg-brand-brown/40" />
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">Approche</span>
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">{t('sectionLabel')}</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-12 md:gap-6 lg:gap-16">
+7 -8
View File
@@ -1,9 +1,11 @@
'use client';
import { useEffect, useRef } from 'react';
import { useTranslations } from "next-intl";
export default function HeroSection() {
const sectionRef = useRef<HTMLElement>(null);
const t = useTranslations('hero');
useEffect(() => {
const section = sectionRef.current;
@@ -36,7 +38,7 @@ export default function HeroSection() {
>
<span className="inline-flex items-center gap-2 font-sans text-xs uppercase tracking-[0.2em] text-brand-beige/50">
<span className="w-6 h-px bg-brand-beige/30" />
Développeur Full Stack &amp; Architecte Web
{t('sectionLabel')}
</span>
</div>
@@ -46,9 +48,7 @@ export default function HeroSection() {
style={{ opacity: 0, transform: 'translateY(28px)', transition: 'opacity 700ms cubic-bezier(0.22,1,0.36,1), transform 700ms cubic-bezier(0.22,1,0.36,1)' }}
>
<h1 className="font-serif leading-[0.95] text-[clamp(36px,5.5vw,88px)] text-brand-beige">
Ensemble,<br />
<em className="not-italic text-brand-beige/70">construisons</em><br />
ce qui dure.
{t('title')}
</h1>
</div>
@@ -58,8 +58,7 @@ export default function HeroSection() {
style={{ opacity: 0, transform: 'translateY(28px)', transition: 'opacity 700ms cubic-bezier(0.22,1,0.36,1), transform 700ms cubic-bezier(0.22,1,0.36,1)' }}
>
<p className="font-sans text-base font-light text-brand-beige/60 max-w-md leading-relaxed">
Je conçois des architectures robustes, scalables et pérennes
des fondations qui supportent la croissance de votre produit dans le temps.
{t('subtitle')}
</p>
</div>
@@ -77,7 +76,7 @@ export default function HeroSection() {
}}
>
<span className="relative">
Voir mes travaux
{t('cta')}
<span className="absolute bottom-0 left-0 w-full h-px bg-brand-beige/40 origin-left scale-x-0 group-hover:scale-x-100 transition-transform duration-300" />
</span>
<svg className="w-4 h-4 group-hover:translate-x-1 transition-transform duration-200" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden="true">
@@ -135,7 +134,7 @@ export default function HeroSection() {
animationDelay: '1s'
}}
>
<span className="font-sans text-[10px] uppercase tracking-[0.15em]">Défiler</span>
<span className="font-sans text-[10px] uppercase tracking-[0.15em]">{t('scrollPrompt')}</span>
<svg
className="w-4 h-4"
style={{ animation: 'arrowBounce 1.8s ease-in-out infinite' }}
+4 -2
View File
@@ -2,6 +2,7 @@
import { useRef, useEffect } from 'react';
import Link from 'next/link';
import { useTranslations } from "next-intl";
type props = {
locale: string;
@@ -15,6 +16,7 @@ type props = {
export function OtherProjects({ locale, projects }: props) {
const ref = useRef<HTMLElement>(null);
const t = useTranslations('projectPage.otherProjects');
useEffect(() => {
const el = ref.current;
@@ -45,12 +47,12 @@ export function OtherProjects({ locale, projects }: props) {
<div className="flex items-center gap-3 mb-6">
<span className="w-6 h-px bg-brand-brown/40" />
<span className="font-sans text-[10px] uppercase tracking-[0.2em] text-brand-brown/40">
Autres projets
{t('sectionLabel')}
</span>
</div>
<h2 className="reveal font-serif text-[clamp(48px,6vw,80px)] leading-none text-brand-brown mb-12">
Voir aussi
{t('title')}
</h2>
<div className="grid gap-6 md:grid-cols-2">
+5 -3
View File
@@ -2,6 +2,7 @@
import { useEffect, useRef } from 'react';
import Link from 'next/link';
import { useTranslations } from "next-intl";
type props = {
title: string;
@@ -13,6 +14,7 @@ type props = {
export function ProjectHero({ title, description, dateLabel, locale, cover }: props) {
const ref = useRef<HTMLElement>(null);
const t = useTranslations('projectPage.hero');
useEffect(() => {
const section = ref.current;
@@ -46,7 +48,7 @@ export function ProjectHero({ title, description, dateLabel, locale, cover }: pr
)}
{/* Back link */}
<div className="relative z-10 px-8 md:px-14 lg:px-20 pt-10">
<div className="relative z-10 px-8 md:px-14 lg:px-20 pt-30">
<div
className="hero-reveal"
style={{ opacity: 0, transform: 'translateY(20px)', transition: 'opacity 500ms ease, transform 500ms cubic-bezier(0.22,1,0.36,1)' }}
@@ -64,7 +66,7 @@ export function ProjectHero({ title, description, dateLabel, locale, cover }: pr
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M7 16l-4-4m0 0l4-4m-4 4h18" />
</svg>
Retour aux projets
{t('backToProjects')}
</Link>
</div>
</div>
@@ -107,7 +109,7 @@ export function ProjectHero({ title, description, dateLabel, locale, cover }: pr
{/* Scroll indicator */}
<div className="relative z-10 flex justify-center pb-8 text-brand-beige/30">
<div className="flex flex-col items-center gap-1.5">
<span className="font-sans text-[10px] uppercase tracking-[0.15em]">Défiler</span>
<span className="font-sans text-[10px] uppercase tracking-[0.15em]">{t('scrollPrompt')}</span>
<svg
className="w-4 h-4"
style={{ animation: 'arrowBounce 1.8s ease-in-out infinite' }}
+6 -4
View File
@@ -1,6 +1,7 @@
'use client';
import { useRef, useEffect } from 'react';
import { useTranslations } from "next-intl";
type props = {
dateLabel: string;
@@ -24,6 +25,7 @@ function MetaItem({ label, children }: { label: string; children: React.ReactNod
export function ProjectMeta({ dateLabel, category, roles, client }: props) {
const ref = useRef<HTMLElement>(null);
const t = useTranslations('projectPage.meta');
useEffect(() => {
const el = ref.current;
@@ -47,16 +49,16 @@ export function ProjectMeta({ dateLabel, category, roles, client }: props) {
<div className="w-full h-px bg-brand-brown/10 mb-10" />
<div className="grid grid-cols-2 gap-8 md:grid-cols-4 md:gap-12">
<MetaItem label="Année">{dateLabel}</MetaItem>
<MetaItem label="Catégorie">{category}</MetaItem>
<MetaItem label="Rôles">
<MetaItem label={t('year')}>{dateLabel}</MetaItem>
<MetaItem label={t('category')}>{category}</MetaItem>
<MetaItem label={t('roles')}>
<div className="flex flex-col gap-1">
{roles.map((role) => (
<span key={role}>{role}</span>
))}
</div>
</MetaItem>
<MetaItem label="Client">{client}</MetaItem>
<MetaItem label={t('client')}>{client}</MetaItem>
</div>
{/* Bottom divider */}
+3 -1
View File
@@ -1,6 +1,7 @@
'use client';
import { useRef, useEffect } from 'react';
import { useTranslations } from "next-intl";
type props = {
technologies: string[];
@@ -8,6 +9,7 @@ type props = {
export function ProjectTechnologies({ technologies }: props) {
const ref = useRef<HTMLElement>(null);
const t = useTranslations('projectPage.technologies');
useEffect(() => {
const el = ref.current;
@@ -32,7 +34,7 @@ export function ProjectTechnologies({ technologies }: props) {
<div className="flex items-center gap-3 mb-6">
<span className="w-6 h-px bg-brand-brown/40" />
<span className="font-sans text-[10px] uppercase tracking-[0.2em] text-brand-brown/40">
Technologies
{t('sectionLabel')}
</span>
</div>
+5 -2
View File
@@ -1,6 +1,8 @@
'use client';
import { useRef, useEffect } from 'react';
import { useTranslations } from "next-intl";
import { Project } from "@/lib/projects/types";
import { ProjectCard } from "../ui/ProjectCard";
@@ -11,6 +13,7 @@ type props = {
export default function WorksSection({ projects, locale }: props) {
const sectionRef = useRef<HTMLElement>(null);
const t = useTranslations('works');
useEffect(() => {
const section = sectionRef.current;
@@ -39,11 +42,11 @@ export default function WorksSection({ projects, locale }: props) {
{/* Section label */}
<div className="reveal flex items-center gap-3 mb-4">
<span className="w-8 h-px bg-brand-brown/40" />
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">Sélection de projets</span>
<span className="font-sans text-[11px] uppercase tracking-[0.2em] text-brand-brown/45">{t('sectionLabel')}</span>
</div>
<h2 className="reveal font-serif text-[clamp(56px,8vw,112px)] text-brand-brown leading-none mb-12 md:mb-16">
Travaux
{t('title')}
</h2>
<div className="w-full">