refactor(i18n): restructure translation system with nested objects and proxy

feat(data): add projects and services data structure for dynamic rendering
refactor(pages): replace hardcoded content with dynamic data-driven components
This commit is contained in:
joyzhao
2025-06-19 10:52:05 +08:00
parent c1f240d007
commit 5b6b9f5d58
7 changed files with 446 additions and 541 deletions

View File

@@ -4,11 +4,15 @@ import GlassHeader from "@/components/GlassHeader";
import Footer from "@/components/Footer";
import { useTranslations, type Lang } from "@/i18n/utils";
import { defaultLang } from "@/i18n/ui";
import { projects } from "@/lib/data";
// 使用Astro.currentLocale获取当前语言环境
const lang = Astro.currentLocale as Lang || defaultLang;
const t = useTranslations(lang);
const pageTitle = t('projects.title');
// 根据当前语言获取项目数据
const currentProjects = projects[lang as keyof typeof projects] || projects.en;
---
<Layout title={pageTitle}>
@@ -41,194 +45,59 @@ const pageTitle = t('projects.title');
<div class="container max-w-6xl mx-auto px-6 md:px-4 relative z-10">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8 items-stretch">
<!-- Taskify App Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-blue-100 dark:bg-blue-800 text-blue-800 dark:text-blue-200 text-xs rounded-full font-medium border border-blue-200 dark:border-blue-700">{t('project.tag.business')}</span>
</div>
<!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
<div class="absolute bottom-4 left-4 right-4">
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
Taskify App
</div>
{currentProjects.map((project) => (
<div class={`group overflow-hidden border border-${project.color}-500/20 hover:border-${project.color}-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative`}>
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class={`px-3 py-1 bg-${project.color}-100 dark:bg-${project.color}-800 text-${project.color}-800 dark:text-${project.color}-200 text-xs rounded-full font-medium border border-${project.color}-200 dark:border-${project.color}-700`}>{t(`project.tag.${project.tag}`)}</span>
</div>
</div>
<div class="p-6 pb-4">
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
<span class="text-purple-500">📱</span>
Taskify App
</h3>
</div>
<div class="px-6 flex-grow">
<div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>A comprehensive task management application with drag-and-drop functionality.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Built with React, TypeScript, and Tailwind CSS for modern development.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Real-time collaboration features with WebSocket integration for instant updates.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Advanced task filtering, sorting, and project management capabilities.</span>
<!-- Project image placeholder -->
<div class={`h-48 bg-gradient-to-br ${project.image.bg} relative overflow-hidden`}>
<div class={`absolute inset-0 bg-gradient-to-br ${project.image.bg} group-hover:${project.image.hover} transition-all duration-500`}></div>
<div class="absolute bottom-4 left-4 right-4">
<div class={`bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono ${project.image.text}`}>
{project.title}
</div>
</div>
</div>
<!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">React</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Node.js</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">MongoDB</span>
<div class="p-6 pb-4">
<h3 class={`text-xl group-hover:text-${project.color}-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4`}>
<span class={`text-${project.color}-500`}>{project.icon}</span>
{project.title}
</h3>
</div>
</div>
<!-- Visit project link -->
<div class="p-6 pt-2">
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
{t('project.visit')}
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
<!-- E-Shop Platform Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-green-100 dark:bg-green-800 text-green-800 dark:text-green-200 text-xs rounded-full font-medium border border-green-200 dark:border-green-700">{t('project.tag.ecommerce')}</span>
</div>
<!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-green-500/20 to-green-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-green-500/10 to-green-600/10 group-hover:from-green-500/20 group-hover:to-green-600/20 transition-all duration-500"></div>
<div class="absolute bottom-4 left-4 right-4">
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-green-400">
E-Shop Platform
<div class="px-6 flex-grow">
<div class="space-y-3">
{project.description.map((desc) => (
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class={`text-${project.color}-500 mt-1`}>•</span>
<span>{desc}</span>
</div>
))}
</div>
</div>
</div>
<div class="p-6 pb-4">
<h3 class="text-xl group-hover:text-green-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
<span class="text-green-500">🛒</span>
E-Shop Platform
</h3>
</div>
<div class="px-6 flex-grow">
<div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-green-500 mt-1">•</span>
<span>A scalable e-commerce platform with Next.js, Stripe payments, and TailwindCSS.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-green-500 mt-1">•</span>
<span>Responsive design with mobile-first approach for optimal user experience.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-green-500 mt-1">•</span>
<span>Integrated payment processing with Stripe for secure transactions.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-green-500 mt-1">•</span>
<span>Admin dashboard for inventory management and order processing.</span>
<!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 mb-4 flex flex-wrap gap-2">
{project.tech.map((tech) => (
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">{tech}</span>
))}
</div>
</div>
<!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Next.js</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Stripe</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
<!-- Visit project link -->
<div class="p-6 pt-2">
<a href={project.link} class={`inline-flex items-center text-sm font-medium text-${project.color}-500 hover:text-${project.color}-600 dark:hover:text-${project.color}-400 transition-colors duration-300`}>
{t('project.visit')}
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
<!-- Visit project link -->
<div class="p-6 pt-2">
<a href="#" class="inline-flex items-center text-sm font-medium text-green-500 hover:text-green-600 dark:hover:text-green-400 transition-colors duration-300">
{t('project.visit')}
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
<!-- Portfolio Site Project -->
<div class="group overflow-hidden border border-purple-500/20 hover:border-purple-500/40 h-full flex flex-col transition-all duration-500 hover:scale-105 bg-white/10 dark:bg-gray-800/50 backdrop-blur-sm rounded-xl relative">
<!-- Project tag - positioned at top right -->
<div class="absolute top-4 right-4 z-10">
<span class="px-3 py-1 bg-purple-100 dark:bg-purple-800 text-purple-800 dark:text-purple-200 text-xs rounded-full font-medium border border-purple-200 dark:border-purple-700">{t('project.tag.portfolio')}</span>
</div>
<!-- Project image placeholder -->
<div class="h-48 bg-gradient-to-br from-purple-500/20 to-purple-600/20 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-br from-purple-500/10 to-purple-600/10 group-hover:from-purple-500/20 group-hover:to-purple-600/20 transition-all duration-500"></div>
<div class="absolute bottom-4 left-4 right-4">
<div class="bg-black/50 backdrop-blur-sm rounded px-3 py-1 text-xs font-mono text-purple-400">
Portfolio Site
</div>
</div>
</div>
<div class="p-6 pb-4">
<h3 class="text-xl group-hover:text-purple-400 transition-colors duration-300 flex items-center gap-2 font-bold mb-4">
<span class="text-purple-500">🌐</span>
Portfolio Site
</h3>
</div>
<div class="px-6 flex-grow">
<div class="space-y-3">
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>My personal portfolio showcasing my work, built with HTML, TailwindCSS, and Alpine.js.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Responsive design with dark mode support and smooth animations.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Optimized for performance with minimal JavaScript and efficient CSS.</span>
</div>
<div class="flex items-start gap-2 text-sm text-muted-foreground group-hover:text-foreground transition-colors duration-300">
<span class="text-purple-500 mt-1">•</span>
<span>Integrated blog section with markdown support for content management.</span>
</div>
</div>
<!-- Tech stack indicators with unified gray styling -->
<div class="mt-6 mb-4 flex flex-wrap gap-2">
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">HTML</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">TailwindCSS</span>
<span class="px-2 py-1 bg-gray-500/10 dark:bg-gray-400/20 text-gray-600 dark:text-gray-300 text-xs rounded-md border border-gray-500/20 dark:border-gray-400/30">Alpine.js</span>
</div>
</div>
<!-- Visit project link -->
<div class="p-6 pt-2">
<a href="#" class="inline-flex items-center text-sm font-medium text-purple-500 hover:text-purple-600 dark:hover:text-purple-400 transition-colors duration-300">
{t('project.visit')}
<svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
</a>
</div>
</div>
))}
</div>
</div>
</section>