Skip to content

Commit 0e48e3b

Browse files
behitekclaude
andcommitted
feat: complete i18n implementation for homepage and contact page
Fully Translated Pages: - ✅ Homepage (/) - Hero section with welcome, greeting, role, tagline - CTA buttons (View My Work, Get in Touch) - Stats section (Followers, Repositories, Years Exp, Available for hire) - About section with bio, education, tech stack - Featured Projects section - Latest Articles section - Final CTA section - ✅ Contact Page (/contact) - Page title and subtitle - "Get in Touch" section - Quick Info (Location, Role, Education) - Interests tags - Response Time section - Collaboration CTA Vietnamese Routes Working: - /vi/ (homepage in Vietnamese) - /vi/contact (contact page in Vietnamese) - /vi/projects (projects page - uses existing content) - /vi/blog (blog listing - uses existing content) How to Use: 1. Visit http://localhost:4321/ (English) 2. Click "EN" button in navbar 3. Switched to /vi/ (Vietnamese) 4. All text automatically displays in Vietnamese 5. Navigation preserved when switching languages Build Status: - ✅ 19 pages built successfully - ✅ 0 errors, 1 minor warning (unused import) - ✅ All Vietnamese routes functional - ✅ Language switcher working perfectly Remaining Work: - Projects and blog pages still use English content (Vietnamese routes exist but content not translated yet) - These pages can be translated later if needed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 7bbcbd8 commit 0e48e3b

4 files changed

Lines changed: 128 additions & 124 deletions

File tree

new-site/src/pages/contact.astro

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,30 @@
22
import BaseLayout from '@layouts/BaseLayout.astro';
33
import SocialIcon from '@components/SocialIcon.astro';
44
import { SITE, SOCIAL_LINKS } from '@utils/constants';
5+
import { getLangFromUrl, useTranslations } from '@i18n/utils';
6+
7+
const lang = getLangFromUrl(Astro.url);
8+
const t = useTranslations(lang);
59
---
610

711
<BaseLayout
8-
title="Contact"
9-
description="Get in touch - always happy to discuss AI, production ML, RAG systems, or self-hosted solutions"
12+
title={t.contact.title}
13+
description={t.contact.subtitle}
1014
>
1115
<div class="container py-12">
1216
<!-- Header -->
1317
<div class="text-center mb-12">
14-
<h1 class="text-4xl md:text-5xl font-bold mb-4">💬 Let's Connect</h1>
18+
<h1 class="text-4xl md:text-5xl font-bold mb-4">{t.contact.title}</h1>
1519
<p class="text-xl text-[var(--color-text-muted)] max-w-2xl mx-auto">
16-
Always happy to discuss AI, production ML, RAG systems, or self-hosted solutions
20+
{t.contact.subtitle}
1721
</p>
1822
</div>
1923

2024
<!-- Contact Grid -->
2125
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
2226
<!-- Left: Social Links -->
2327
<div class="space-y-4">
24-
<h2 class="text-2xl font-bold mb-6">Get in Touch</h2>
28+
<h2 class="text-2xl font-bold mb-6">{t.contact.getInTouch}</h2>
2529

2630
{Object.entries(SOCIAL_LINKS).map(([key, social]) => (
2731
<a
@@ -60,70 +64,70 @@ import { SITE, SOCIAL_LINKS } from '@utils/constants';
6064
<div class="space-y-6">
6165
<!-- Quick Info -->
6266
<div class="card">
63-
<h3 class="text-xl font-bold mb-4">Quick Info</h3>
67+
<h3 class="text-xl font-bold mb-4">{t.contact.quickInfo.title}</h3>
6468
<div class="space-y-3 text-[var(--color-text-muted)]">
6569
<div class="flex items-start gap-3">
6670
<span class="text-2xl">📍</span>
6771
<div>
68-
<p class="font-medium text-[var(--color-text-base)]">Location</p>
69-
<p>Hanoi, Vietnam 🇻🇳</p>
72+
<p class="font-medium text-[var(--color-text-base)]">{t.contact.quickInfo.location}</p>
73+
<p>{t.contact.quickInfo.locationValue}</p>
7074
</div>
7175
</div>
7276
<div class="flex items-start gap-3">
7377
<span class="text-2xl">💼</span>
7478
<div>
75-
<p class="font-medium text-[var(--color-text-base)]">Role</p>
76-
<p>AI Engineer</p>
79+
<p class="font-medium text-[var(--color-text-base)]">{t.contact.quickInfo.role}</p>
80+
<p>{t.contact.quickInfo.roleValue}</p>
7781
</div>
7882
</div>
7983
<div class="flex items-start gap-3">
8084
<span class="text-2xl">🎓</span>
8185
<div>
82-
<p class="font-medium text-[var(--color-text-base)]">Education</p>
83-
<p>Master's in Information Science (JAIST)</p>
86+
<p class="font-medium text-[var(--color-text-base)]">{t.contact.quickInfo.education}</p>
87+
<p>{t.contact.quickInfo.educationValue}</p>
8488
</div>
8589
</div>
8690
</div>
8791
</div>
8892

8993
<!-- Interests -->
9094
<div class="card">
91-
<h3 class="text-xl font-bold mb-4">Interests</h3>
95+
<h3 class="text-xl font-bold mb-4">{t.contact.interests.title}</h3>
9296
<div class="flex flex-wrap gap-2">
93-
<span class="category-badge category-ai">AI/ML</span>
94-
<span class="category-badge category-ai">NLP</span>
95-
<span class="category-badge category-ai">RAG</span>
96-
<span class="category-badge category-ai">LLMs</span>
97-
<span class="category-badge category-python">Python</span>
98-
<span class="category-badge category-data">IR</span>
99-
<span class="category-badge category-tutorial">Teaching</span>
97+
<span class="category-badge category-ai">{t.contact.interests.aiml}</span>
98+
<span class="category-badge category-ai">{t.contact.interests.nlp}</span>
99+
<span class="category-badge category-ai">{t.contact.interests.rag}</span>
100+
<span class="category-badge category-ai">{t.contact.interests.llms}</span>
101+
<span class="category-badge category-python">{t.contact.interests.python}</span>
102+
<span class="category-badge category-data">{t.contact.interests.ir}</span>
103+
<span class="category-badge category-tutorial">{t.contact.interests.teaching}</span>
100104
<span class="px-3 py-1 text-sm font-medium bg-slate-100 dark:bg-slate-800 rounded-full">
101-
Self-hosting
105+
{t.contact.interests.selfHosting}
102106
</span>
103107
</div>
104108
</div>
105109

106110
<!-- Availability -->
107111
<div class="card bg-gradient-to-br from-primary-50 to-accent-cyan/5 dark:from-primary-950 dark:to-slate-900 border-primary-200 dark:border-primary-800">
108-
<h3 class="text-xl font-bold mb-3">📬 Response Time</h3>
112+
<h3 class="text-xl font-bold mb-3">{t.contact.availability.title}</h3>
109113
<p class="text-[var(--color-text-muted)]">
110-
I typically respond to emails and LinkedIn messages within 24-48 hours. For quick questions, Twitter/X DMs work best!
114+
{t.contact.availability.text}
111115
</p>
112116
</div>
113117
</div>
114118
</div>
115119

116120
<!-- CTA Section -->
117121
<div class="text-center mt-16 p-8 card bg-gradient-to-br from-primary-600 to-accent-cyan text-white">
118-
<h2 class="text-2xl font-bold mb-3">Open to Collaboration</h2>
122+
<h2 class="text-2xl font-bold mb-3">{t.contact.cta.title}</h2>
119123
<p class="text-lg mb-6 opacity-90">
120-
Interested in collaborating on AI/ML projects, writing guest posts, or speaking opportunities?
124+
{t.contact.cta.subtitle}
121125
</p>
122126
<a
123127
href="mailto:hello@behitek.com?subject=Collaboration Inquiry"
124128
class="btn bg-white text-primary-600 hover:bg-slate-50 inline-flex items-center"
125129
>
126-
📧 Send me an email
130+
{t.contact.cta.button}
127131
<svg class="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
128132
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
129133
</svg>

new-site/src/pages/index.astro

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import ProjectCard from '@components/ProjectCard.astro';
66
import SocialIcon from '@components/SocialIcon.astro';
77
import { SITE, EDUCATION, TECH_STACK, STATS, SOCIAL_LINKS } from '@utils/constants';
88
import { readingTime } from '@utils/helpers';
9+
import { getLangFromUrl, useTranslations } from '@i18n/utils';
10+
11+
const lang = getLangFromUrl(Astro.url);
12+
const t = useTranslations(lang);
913
1014
// Get featured projects
1115
const allProjects = await getCollection('projects');
@@ -43,36 +47,33 @@ const recentPosts = allPosts
4347
<div class="text-left animate-fade-in">
4448
<div class="inline-block mb-4">
4549
<span class="px-4 py-2 bg-primary-100 dark:bg-primary-900 text-primary-700 dark:text-primary-300 rounded-full text-sm font-medium">
46-
👋 Welcome to my portfolio
50+
{t.home.welcome}
4751
</span>
4852
</div>
4953

5054
<h1 class="text-5xl md:text-6xl lg:text-7xl font-bold mb-6 leading-tight">
51-
Hi, I'm<br/>
52-
<span class="gradient-text">Hieu Nguyen</span>
55+
{t.home.greeting}<br/>
56+
<span class="gradient-text">{t.home.name}</span>
5357
</h1>
5458

5559
<p class="text-2xl md:text-3xl text-[var(--color-text-muted)] mb-4 font-medium">
56-
AI Engineer
60+
{t.home.role}
5761
</p>
5862

5963
<p class="text-lg text-[var(--color-text-muted)] mb-8 leading-relaxed">
60-
Building production-ready AI systems with <span class="text-primary-600 dark:text-primary-400 font-semibold">NLP</span>,
61-
<span class="text-primary-600 dark:text-primary-400 font-semibold">RAG</span>, and
62-
<span class="text-primary-600 dark:text-primary-400 font-semibold">LLMs</span>.
63-
Passionate about bringing AI into real-world applications.
64+
{t.home.tagline}
6465
</p>
6566

6667
<!-- CTA Buttons -->
6768
<div class="flex flex-wrap items-center gap-4 mb-8">
6869
<a href="/projects" class="btn-primary">
69-
View My Work
70+
{t.home.cta.viewWork}
7071
<svg class="w-5 h-5 ml-2 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
7172
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
7273
</svg>
7374
</a>
7475
<a href="/contact" class="btn-secondary">
75-
Get in Touch
76+
{t.home.cta.getInTouch}
7677
</a>
7778
</div>
7879

@@ -106,23 +107,23 @@ const recentPosts = allPosts
106107
<!-- Status indicator -->
107108
<div class="absolute bottom-8 right-8 flex items-center gap-2 bg-white dark:bg-slate-800 px-4 py-2 rounded-full shadow-lg">
108109
<div class="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
109-
<span class="text-sm font-medium">Available for hire</span>
110+
<span class="text-sm font-medium">{t.home.status}</span>
110111
</div>
111112
</div>
112113

113114
<!-- Quick Stats -->
114115
<div class="grid grid-cols-3 gap-4 w-full max-w-sm">
115116
<div class="text-center p-4 bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm rounded-xl shadow-soft">
116117
<p class="text-2xl font-bold text-primary-600">{STATS.followers}</p>
117-
<p class="text-xs text-[var(--color-text-muted)]">Followers</p>
118+
<p class="text-xs text-[var(--color-text-muted)]">{t.home.stats.followers}</p>
118119
</div>
119120
<div class="text-center p-4 bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm rounded-xl shadow-soft">
120121
<p class="text-2xl font-bold text-primary-600">{STATS.repositories}</p>
121-
<p class="text-xs text-[var(--color-text-muted)]">Repositories</p>
122+
<p class="text-xs text-[var(--color-text-muted)]">{t.home.stats.repositories}</p>
122123
</div>
123124
<div class="text-center p-4 bg-white/80 dark:bg-slate-800/80 backdrop-blur-sm rounded-xl shadow-soft">
124125
<p class="text-2xl font-bold text-primary-600">5+</p>
125-
<p class="text-xs text-[var(--color-text-muted)]">Years Exp</p>
126+
<p class="text-xs text-[var(--color-text-muted)]">{t.home.stats.yearsExp}</p>
126127
</div>
127128
</div>
128129
</div>
@@ -142,9 +143,9 @@ const recentPosts = allPosts
142143
<section class="section bg-[var(--color-bg-base)]">
143144
<div class="container">
144145
<div class="text-center mb-12">
145-
<h2 class="text-4xl font-bold mb-4">About Me</h2>
146+
<h2 class="text-4xl font-bold mb-4">{t.home.about.title}</h2>
146147
<p class="text-lg text-[var(--color-text-muted)] max-w-2xl mx-auto">
147-
AI Engineer with Master's degree from JAIST, specializing in production ML systems
148+
{t.home.about.subtitle}
148149
</p>
149150
</div>
150151

@@ -154,21 +155,19 @@ const recentPosts = allPosts
154155
<div class="flex items-start gap-4">
155156
<div class="text-4xl">👨‍💻</div>
156157
<div class="flex-1">
157-
<h3 class="text-2xl font-bold mb-4">Hello there!</h3>
158+
<h3 class="text-2xl font-bold mb-4">{t.home.about.greeting}</h3>
158159
<div class="space-y-4 text-[var(--color-text-muted)] leading-relaxed">
159160
<p>
160-
I'm Hieu Nguyen, an <strong class="text-[var(--color-text-base)]">AI Engineer from Vietnam 🇻🇳</strong> with a passion for transforming research into production-ready systems.
161+
{t.home.about.bio1}
161162
</p>
162163
<p>
163-
My expertise lies in <strong class="text-[var(--color-text-base)]">Natural Language Processing, RAG systems, and Large Language Models</strong>.
164-
I specialize in building scalable AI solutions that solve real-world problems.
164+
{t.home.about.bio2}
165165
</p>
166166
<p>
167-
🎓 I hold a <strong class="text-[var(--color-text-base)]">{EDUCATION.degree}</strong> from <strong class="text-[var(--color-text-base)]">{EDUCATION.school}</strong> in Japan, where I deepened my knowledge in information retrieval and machine learning.
167+
🎓 {t.home.about.bio3.replace('{degree}', EDUCATION.degree).replace('{school}', EDUCATION.school)}
168168
</p>
169169
<p>
170-
💡 When I'm not coding, you'll find me exploring <a href="https://www.reddit.com/r/selfhosted/" class="link" target="_blank" rel="noopener noreferrer">self-hosted solutions</a>,
171-
contributing to open source, or writing about AI/ML on my blog.
170+
💡 {t.home.about.bio4}
172171
</p>
173172
</div>
174173
</div>
@@ -178,7 +177,7 @@ const recentPosts = allPosts
178177
<!-- Education Card -->
179178
<div class="md:col-span-4 card bg-gradient-to-br from-primary-50 to-cyan-50 dark:from-primary-950 dark:to-slate-900 border-primary-200 dark:border-primary-800">
180179
<div class="text-3xl mb-3">🎓</div>
181-
<h3 class="text-lg font-bold mb-2">Education</h3>
180+
<h3 class="text-lg font-bold mb-2">{t.home.education.title}</h3>
182181
<p class="text-sm text-[var(--color-text-muted)] mb-2">{EDUCATION.degree}</p>
183182
<p class="text-sm font-semibold text-primary-600 dark:text-primary-400">{EDUCATION.school}</p>
184183
<p class="text-xs text-[var(--color-text-muted)] mt-1">{EDUCATION.country}</p>
@@ -188,7 +187,7 @@ const recentPosts = allPosts
188187
<div class="md:col-span-12 card">
189188
<div class="flex items-center gap-3 mb-6">
190189
<div class="text-3xl">🛠️</div>
191-
<h3 class="text-2xl font-bold">Tech Stack & Skills</h3>
190+
<h3 class="text-2xl font-bold">{t.home.techStack.title}</h3>
192191
</div>
193192
<div class="space-y-6">
194193
{Object.entries(TECH_STACK).map(([category, skills]) => (
@@ -215,9 +214,9 @@ const recentPosts = allPosts
215214
<section class="section bg-[var(--color-bg-secondary)]">
216215
<div class="container">
217216
<div class="text-center mb-12">
218-
<h2 class="text-4xl font-bold mb-4">🚀 Featured Projects</h2>
217+
<h2 class="text-4xl font-bold mb-4">{t.home.featuredProjects.title}</h2>
219218
<p class="text-lg text-[var(--color-text-muted)]">
220-
Check out some of my recent work and contributions
219+
{t.home.featuredProjects.subtitle}
221220
</p>
222221
</div>
223222

@@ -229,7 +228,7 @@ const recentPosts = allPosts
229228

230229
<div class="text-center">
231230
<a href="/projects" class="btn-primary">
232-
View All Projects
231+
{t.home.featuredProjects.viewAll}
233232
<svg class="w-5 h-5 ml-2 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
234233
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
235234
</svg>
@@ -243,9 +242,9 @@ const recentPosts = allPosts
243242
<section class="section bg-[var(--color-bg-base)]">
244243
<div class="container">
245244
<div class="text-center mb-12">
246-
<h2 class="text-4xl font-bold mb-4">✍️ Latest Articles</h2>
245+
<h2 class="text-4xl font-bold mb-4">{t.home.latestArticles.title}</h2>
247246
<p class="text-lg text-[var(--color-text-muted)]">
248-
Thoughts on AI, ML, and software engineering
247+
{t.home.latestArticles.subtitle}
249248
</p>
250249
</div>
251250

@@ -265,7 +264,7 @@ const recentPosts = allPosts
265264

266265
<div class="text-center">
267266
<a href="/blog" class="btn-primary">
268-
View All Articles
267+
{t.home.latestArticles.viewAll}
269268
<svg class="w-5 h-5 ml-2 inline-block" fill="none" stroke="currentColor" viewBox="0 0 24 24">
270269
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 8l4 4m0 0l-4 4m4-4H3"></path>
271270
</svg>
@@ -284,18 +283,17 @@ const recentPosts = allPosts
284283

285284
<div class="container relative z-10 text-center">
286285
<h2 class="text-4xl md:text-5xl font-bold mb-6">
287-
Let's Build Something Amazing Together
286+
{t.home.cta2.title}
288287
</h2>
289288
<p class="text-xl mb-8 opacity-90 max-w-2xl mx-auto">
290-
Looking for an AI engineer to bring your ideas to life?
291-
I'm available for consulting, collaboration, and full-time opportunities.
289+
{t.home.cta2.subtitle}
292290
</p>
293291
<div class="flex items-center justify-center gap-4 flex-wrap">
294292
<a href="/contact" class="btn bg-white text-primary-600 hover:bg-slate-50 text-lg px-8 py-4">
295-
📧 Get in Touch
293+
{t.home.cta2.getInTouch}
296294
</a>
297295
<a href="/projects" class="btn border-2 border-white text-white hover:bg-white/10 text-lg px-8 py-4">
298-
🚀 View My Work
296+
{t.home.cta2.viewWork}
299297
</a>
300298
</div>
301299
</div>

0 commit comments

Comments
 (0)