Where I Built the Foundation
+{copy.title}
Where I've Made an Impact
+{copy.title}
- Hi, I'm
- Amirhossein Khalili
+
+ {copy.greeting}
+ {copy.name}
-
- Product engineer building useful, resilient software. -
+{copy.subtitle}
{/* Action Buttons */} diff --git a/src/components/IsometricFooter/IsoTypes.ts b/src/components/IsometricFooter/IsoTypes.ts index 3e1b12b..23c5c58 100644 --- a/src/components/IsometricFooter/IsoTypes.ts +++ b/src/components/IsometricFooter/IsoTypes.ts @@ -1,4 +1,4 @@ -import React from 'react'; +import type React from 'react'; export type FooterContactId = 'phone' | 'linkedin' | 'github' | 'telegram'; @@ -72,6 +72,7 @@ export interface IsoSignpostProps { export interface IsometricSceneProps { activePost: FooterContactId | null; + ariaLabel: string; onPostHover?: (id: FooterContactId | null) => void; onPostClick?: (id: FooterContactId) => void; } diff --git a/src/components/IsometricFooter/IsometricFooter.tsx b/src/components/IsometricFooter/IsometricFooter.tsx index 01dcab9..4e0a44d 100644 --- a/src/components/IsometricFooter/IsometricFooter.tsx +++ b/src/components/IsometricFooter/IsometricFooter.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useState } from 'react'; +import { useState } from 'react'; import type { ContactItem, FooterContactId } from './IsoTypes'; import IsometricScene from './IsometricScene'; import { @@ -11,6 +11,7 @@ import { TelegramIcon, } from './IsoElements'; import styles from './IsometricFooter.module.css'; +import { messagesByLocale, type Locale } from '@/i18n/content'; export const contacts: ContactItem[] = [ { @@ -43,7 +44,12 @@ export const contacts: ContactItem[] = [ }, ]; -export default function IsometricFooter() { +export default function IsometricFooter({ locale }: { locale: Locale }) { + const copy = messagesByLocale[locale].footer; + const localizedContacts = contacts.map((contact) => ({ + ...contact, + name: copy[contact.id], + })); const [activePost, setActivePost] = useState- Let's build something meaningful. + {copy.title}
- Open to opportunities and interesting projects. + {copy.subtitle}
{/* Email Pill Button */} @@ -74,12 +80,14 @@ export default function IsometricFooter() {Milestones Along the Way
+{copy.title}
- Products I've Brought to Life + {copy.title}
{project.title}
- {project.link && ( + {project.link && isRtl && ( + + )} ++ {project.title} +
+ {project.link && !isRtl && (From Pixel to Product
+ {copy.eyebrow} ++ {copy.title} +
-- I began as a digital artist, designing visual stories. Curiosity turned - into code, and code into systems that solve real problems. Today, I - build products end-to-end using agentic workflows that blend creativity, - engineering, and product thinking. -
+{copy.description}
-
- {steps.map((step) => {
- const StepIcon = step.icon;
+ {copy.steps.map((step, index) => {
+ const StepIcon = stepIcons[index];
return (
-
- +
-
diff --git a/src/components/ScenicHeroJourney.tsx b/src/components/ScenicHeroJourney.tsx
index 32254cb..2c41772 100644
--- a/src/components/ScenicHeroJourney.tsx
+++ b/src/components/ScenicHeroJourney.tsx
@@ -1,6 +1,5 @@
'use client';
-import React from 'react';
import { HeroSection } from './HeroSection';
import { RiverJourney } from './RiverJourney';
import {
@@ -10,6 +9,7 @@ import {
HeroIllustrationMoon,
} from './HeroIllustrations';
import styles from './ScenicHeroJourney.module.css';
+import { messagesByLocale, type Locale } from '@/i18n/content';
function HeroBackdrop() {
return (
@@ -22,15 +22,17 @@ function HeroBackdrop() {
);
}
-export const ScenicHeroJourney: React.FC = () => {
+export const ScenicHeroJourney = ({ locale }: { locale: Locale }) => {
+ const copy = messagesByLocale[locale];
+
return (
-); }; diff --git a/src/components/SiteLoader.tsx b/src/components/SiteLoader.tsx index ef0f960..743d639 100644 --- a/src/components/SiteLoader.tsx +++ b/src/components/SiteLoader.tsx @@ -6,6 +6,7 @@ import { experiences } from '@/data/experience'; import { milestones } from '@/data/milestones'; import { projects } from '@/data/projects'; import { skillsByDiscipline } from '@/data/skills'; +import { messagesByLocale, type Locale } from '@/i18n/content'; import styles from './SiteLoader.module.css'; const DARK_PROJECT_IDS = new Set([ @@ -78,7 +79,8 @@ const preloadImage = (src: string, onSettled: () => void) => type LoaderPhase = 'loading' | 'leaving' | 'hidden'; -export function SiteLoader() { +export function SiteLoader({ locale }: { locale: Locale }) { + const copy = messagesByLocale[locale].loader; const [progress, setProgress] = useState(0); const [phase, setPhase] = useState
+ -- + + ('loading'); @@ -149,7 +151,7 @@ export function SiteLoader() { role="status" aria-live="polite" aria-busy={phase === 'loading'} - aria-label={`Loading portfolio: ${progress}%`} + aria-label={copy.ariaLabel(progress)} > @@ -163,15 +165,15 @@ export function SiteLoader() {
- Amirhossein Khalili + {copy.signature}
-Assembling the experience
+{copy.message}