refactor: 优化组件国际化实现

- 将客户端组件改为服务端组件,使用 getTranslations
- LocaleSwitcher 简化为接收 switchUrl prop
- ProjectCard/ProjectList/ExternalLinkCard 等组件支持 i18n
- 优化 webhook 去重查询,关联 links 数据
- 移除 ProjectDetail 中的客户端交互逻辑(ShareButtons 暂时禁用)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-29 19:58:23 +08:00
co-authored by Claude
parent 6303fd7ae6
commit 3869bb23bb
10 changed files with 143 additions and 93 deletions
+15 -7
View File
@@ -1,4 +1,5 @@
import Link from 'next/link'
import { getTranslations } from 'next-intl/server'
interface ProjectCardProps {
project: {
@@ -30,11 +31,17 @@ function getProjectIcon(tags: Array<{ name: string }>): string {
return '✨'
}
export function ProjectCard({ project, locale, featured = false }: ProjectCardProps) {
export async function ProjectCard({ project, locale, featured = false }: ProjectCardProps) {
const t = await getTranslations('common')
const icon = getProjectIcon(project.tags)
const displayName = locale === 'en' && project.nameEn ? project.nameEn : project.name
const displayDescription = locale === 'en' && project.descriptionEn ? project.descriptionEn : project.description
// Helper to get display name for tag based on locale
const getTagName = (tag: { name: string; nameEn?: string | null }) => {
return locale === 'en' && tag.nameEn ? tag.nameEn : tag.name
}
return (
<article
className={`bg-white dark:bg-surface-dark border-2 border-black dark:border-gray-600 p-6 ${
@@ -61,7 +68,7 @@ export function ProjectCard({ project, locale, featured = false }: ProjectCardPr
key={tag.id}
className="bg-gray-100 dark:bg-gray-800 px-2 py-1 text-[10px] uppercase font-display font-bold border border-gray-300 dark:border-gray-600 text-gray-600 dark:text-gray-300"
>
{tag.name}
{getTagName(tag)}
</span>
))}
</div>
@@ -71,7 +78,7 @@ export function ProjectCard({ project, locale, featured = false }: ProjectCardPr
href={`/${locale}/projects/${project.slug}`}
className="inline-flex items-center font-display font-bold text-sm uppercase hover:text-secondary dark:hover:text-primary group"
>
VIEW DETAILS{' '}
{t('viewDetails')}{' '}
<span className="ml-1 transform group-hover:translate-x-1 transition-transform"></span>
</Link>
</div>
@@ -80,21 +87,22 @@ export function ProjectCard({ project, locale, featured = false }: ProjectCardPr
}
// Special card for "Submit Your Project" CTA
export function SubmitProjectCard({ locale }: { locale: string }) {
export async function SubmitProjectCard({ locale }: { locale: string }) {
const t = await getTranslations('project')
return (
<article className="bg-primary border-2 border-black dark:border-gray-600 p-6 shadow-neo hover:shadow-neo-hover hover:-translate-y-1 transition-all duration-200 flex flex-col h-full justify-center items-center text-center group">
<div className="bg-white dark:bg-black p-4 rounded-full border-2 border-black mb-4 group-hover:scale-110 transition-transform">
<span className="text-3xl dark:text-primary">+</span>
</div>
<h3 className="font-display text-xl md:text-2xl font-bold text-black mb-2">Submit Your Project</h3>
<h3 className="font-display text-xl md:text-2xl font-bold text-black mb-2">{t('submitProjectTitle')}</h3>
<p className="text-black mb-6 font-sans text-sm px-4">
Have an AI tool worth sharing? Add it to Agent Park.
{t('submitProjectDescription')}
</p>
<Link
href="#"
className="bg-black text-white dark:bg-black dark:text-primary border-2 border-black dark:border-black px-6 py-2 font-display text-sm font-bold uppercase hover:bg-white hover:text-black dark:hover:bg-white dark:hover:text-black transition-colors"
>
SUBMIT NOW
{t('submitNow')}
</Link>
</article>
)