Translate various components to Turkish, including blog content, contact forms, newsletter, and navigation links. Update labels, placeholders, and error messages for better localization. Adjust layout and styling for improved user experience.

This commit is contained in:
poyrazavsever
2026-03-11 00:04:31 +03:00
parent 8d3a51f401
commit 4ac6c518c6
18 changed files with 156 additions and 149 deletions
+5 -5
View File
@@ -8,9 +8,9 @@ import { AnnouncementBar } from "poyraz-ui/organisms";
export const metadata: Metadata = {
title:
"Poyraz Avsever - Portfolio - Freelancer - Fullstack Developer - Web Developer",
"Poyraz Avsever | Portfolyo | Freelancer | Full-stack Geliştirici | Web Geliştirici",
description:
"Poyraz Avsever's personal portfolio website showcasing projects, skills, and services as a freelancer and fullstack web developer. A young person passionate about coding and technology.",
"Poyraz Avsever'in projelerini, yetkinliklerini ve hizmetlerini sergilediği kişisel portfolyo sitesi. Yazılıma ve teknolojiye tutkuyla bağlı genç bir geliştirici.",
icons: {
icon: "/favicon.ico",
},
@@ -47,7 +47,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="tr">
<body className="min-h-dvh bg-background text-foreground antialiased">
<div className="mx-auto flex w-full max-w-4xl flex-col overflow-hidden px-4 py-4 sm:px-6">
<SiteNavbar />
@@ -62,11 +62,11 @@ export default function RootLayout({
rel="noreferrer"
className="text-xs font-bold underline"
>
Learn More -&gt;
İncele -&gt;
</Link>
}
>
New components added this week!
Bu hafta yeni bileşenler eklendi!
</AnnouncementBar>
<main className="flex-1 overflow-hidden py-4">{children}</main>
</div>
+11 -11
View File
@@ -10,7 +10,7 @@ import { EDUCATION } from "@/data/education";
import { EXPERIENCE } from "@/data/experience";
const ABOUT_TEXT =
"Since I was introduced to software in middle school, I've been trying to learn and improve continuously. During high school, my enthusiasm for learning grew and I had the opportunity to explore various technologies in web development. Towards the end of high school, I stepped into the mobile world. Currently, I'm actively creating, developing, and most importantly, still learning.";
"Ortaokulda yazılımla tanıştığımdan beri sürekli öğrenmeye ve kendimi geliştirmeye çalışıyorum. Lise yıllarında öğrenme hevesim daha da arttı ve web geliştirme tarafında farklı teknolojileri keşfetme fırsatı buldum. Lisenin sonlarına doğru mobil dünyasına da adım attım. Şu an aktif olarak üretiyor, geliştiriyor ve en önemlisi hâlâ öğrenmeye devam ediyorum.";
const CERTIFICATE_PREVIEW = certificates.slice(0, 4);
@@ -49,7 +49,7 @@ export function AboutContent() {
<button
type="button"
className="cursor-pointer text-left"
aria-label="Open all certificates"
aria-label="Tüm sertifikaları"
>
<Card className="rounded-sm border-border p-4 transition-colors hover:border-zinc-700">
<div className="grid grid-cols-2 gap-2">
@@ -70,7 +70,7 @@ export function AboutContent() {
</SheetTrigger>
<SheetContent side="right" className="w-full max-w-xl p-4">
<SheetTitle>All Certificates</SheetTitle>
<SheetTitle>Tüm Sertifikalar</SheetTitle>
<div className="mt-4 grid max-h-[90dvh] gap-3 overflow-y-auto pr-1">
{certificates.map((item) => (
<Card key={`${item.name}-${item.date}`} className="rounded-sm border-border p-3">
@@ -125,10 +125,10 @@ export function AboutContent() {
<Link href="/about/references" className="block">
<Card className="h-full rounded-sm border-border p-4 transition-colors hover:border-zinc-700">
<Typography variant="large" className="text-base leading-tight">
References
Referanslar
</Typography>
<Typography variant="small" className="mt-1 text-muted-foreground">
Open the full reference list in a dedicated detail page.
Tüm referansları ayrı bir detay sayfasında görüntüle.
</Typography>
</Card>
</Link>
@@ -136,10 +136,10 @@ export function AboutContent() {
<Link href="/about/volunteer-community" className="block">
<Card className="h-full rounded-sm border-border p-4 transition-colors hover:border-zinc-700">
<Typography variant="large" className="text-base leading-tight">
Volunteer & Community
Gönüllülük ve Topluluk
</Typography>
<Typography variant="small" className="mt-1 text-muted-foreground">
Timeline and contribution details in a separate detail page.
Zaman çizelgesi ve katkı detaylarını ayrı bir detay sayfasında incele.
</Typography>
</Card>
</Link>
@@ -149,21 +149,21 @@ export function AboutContent() {
<button
type="button"
className="cursor-pointer text-left"
aria-label="Open bookmarks"
aria-label="Yer imlerini aç"
>
<Card className="h-full rounded-sm border-border p-4 transition-colors hover:border-zinc-700">
<Typography variant="large" className="text-base leading-tight">
Bookmark
Yer İmleri
</Typography>
<Typography variant="small" className="mt-1 text-muted-foreground">
Quick access links in a sheet panel.
Hızlı erişim bağlantılarını bir sheet içinde görüntüle.
</Typography>
</Card>
</button>
</SheetTrigger>
<SheetContent side="right" className="w-full max-w-xl p-4">
<SheetTitle>Bookmarks</SheetTitle>
<SheetTitle>Yer İmleri</SheetTitle>
<div className="mt-4 grid max-h-[90dvh] gap-3 overflow-y-auto pr-1">
{BOOKMARKS.map((item) => (
<Card key={item.id} className="rounded-sm border-border p-3">
+2 -2
View File
@@ -38,7 +38,7 @@ export function BlogContent() {
<div className="grid gap-3 md:grid-rows-[auto_1fr]">
<Card className="rounded-sm border-border p-4">
<Typography variant="large">Categories</Typography>
<Typography variant="large">Kategoriler</Typography>
<div className="mt-3 flex flex-wrap gap-2">
{BLOG_CATEGORIES.map((category, index) => (
<Badge
@@ -53,7 +53,7 @@ export function BlogContent() {
</Card>
<Card className="rounded-sm border-border p-4">
<Typography variant="large">Recent comments</Typography>
<Typography variant="large">Son yorumlar</Typography>
<div className="mt-3 space-y-2">
{RECENT_COMMENTS.map((comment) => (
<Card key={comment.id} className="rounded-sm border-border p-3">
+20 -20
View File
@@ -46,7 +46,7 @@ function MermaidBlock({ chart }: { chart: string }) {
}
} catch {
if (mounted) {
setError("Mermaid diagram could not be rendered.");
setError("Mermaid diyagramı oluşturulamadı.");
}
}
};
@@ -71,7 +71,7 @@ function MermaidBlock({ chart }: { chart: string }) {
return (
<Card className="rounded-sm border-border p-3">
<Typography variant="small" className="text-muted-foreground">
Rendering diagram...
Diyagram hazırlanıyor...
</Typography>
</Card>
);
@@ -138,9 +138,9 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
...item.replies,
{
id: `reply-${Date.now()}`,
author: "You (GitHub)",
author: "Sen (GitHub)",
avatar: "/logo/logo.jpeg",
date: "Just now",
date: "Az önce",
content,
likes: 0,
},
@@ -154,9 +154,9 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
setComments((prev) => [
{
id: `comment-${Date.now()}`,
author: "You (GitHub)",
author: "Sen (GitHub)",
avatar: "/logo/logo.jpeg",
date: "Just now",
date: "Az önce",
content,
likes: 0,
replies: [],
@@ -184,7 +184,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
href="/blog"
className="inline-flex items-center rounded-sm border border-border px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground"
>
{"<- Back to blog"}
{"<- Blog'a dön"}
</Link>
<header className="space-y-3">
@@ -216,8 +216,8 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
variant={liked ? "default" : "outline"}
className="h-9 w-9 rounded-sm p-0"
onClick={toggleLike}
aria-label={`Like post (${likeCount})`}
title={`Like (${likeCount})`}
aria-label={`Yazıyı beğen (${likeCount})`}
title={`Beğen (${likeCount})`}
>
<Icon icon={liked ? "mdi:heart" : "mdi:heart-outline"} width={18} height={18} />
</Button>
@@ -228,8 +228,8 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
type="button"
variant="outline"
className="h-9 w-9 rounded-sm p-0"
aria-label={`Open comments (${comments.length})`}
title={`Comments (${comments.length})`}
aria-label={`Yorumları (${comments.length})`}
title={`Yorumlar (${comments.length})`}
>
<Icon icon="mdi:comment-outline" width={18} height={18} />
</Button>
@@ -237,7 +237,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
<SheetContent side="right" className="flex h-dvh w-full max-w-xl flex-col p-0">
<div className="border-b border-border px-4 py-3">
<SheetTitle>Comments</SheetTitle>
<SheetTitle>Yorumlar</SheetTitle>
</div>
<div className="flex min-h-0 flex-1 flex-col gap-3 p-4">
@@ -265,7 +265,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
</Typography>
<div className="mt-2 flex items-center gap-2">
<Button type="button" variant="outline" size="sm" className="rounded-sm">
Like ({item.likes})
Beğen ({item.likes})
</Button>
<Button
type="button"
@@ -274,7 +274,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
className="rounded-sm"
onClick={() => handleReplyClick(item.id, item.author)}
>
Reply
Yanıtla
</Button>
</div>
@@ -319,14 +319,14 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
{!githubAuthed ? (
<Card className="rounded-sm border-border p-3">
<Typography variant="small" className="text-muted-foreground">
You need to sign in with GitHub before posting comments.
Yorum yapmadan önce GitHub ile giriş yapman gerekiyor.
</Typography>
<Button
type="button"
className="mt-2 rounded-sm"
onClick={() => setGithubAuthed(true)}
>
Continue with GitHub
GitHub ile devam et
</Button>
</Card>
) : null}
@@ -335,7 +335,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
<Card className="rounded-sm border-border p-2">
<div className="flex flex-wrap items-center justify-between gap-2">
<Typography variant="small" className="text-muted-foreground">
Replying to {replyTo.author}
{replyTo.author} kullanıcısına yanıt yazıyorsun
</Typography>
<Button
type="button"
@@ -344,7 +344,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
className="rounded-sm"
onClick={() => setReplyTo(null)}
>
Cancel
Vazgeç
</Button>
</div>
</Card>
@@ -354,7 +354,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
<Textarea
value={draft}
onChange={(event) => setDraft(event.target.value)}
placeholder={githubAuthed ? "Write your comment..." : "Sign in with GitHub first"}
placeholder={githubAuthed ? "Yorumunu yaz..." : "Önce GitHub ile giriş yap"}
className="min-h-24 rounded-sm"
disabled={!githubAuthed}
/>
@@ -365,7 +365,7 @@ export function BlogDetailContent({ post, engagement }: BlogDetailContentProps)
onClick={handleSubmitComment}
disabled={!githubAuthed || !draft.trim()}
>
Post Comment
Yorumu Gönder
</Button>
</div>
</Card>
+13 -13
View File
@@ -14,9 +14,9 @@ export function ContactContent() {
event.preventDefault();
if (!isValid) return;
const subject = encodeURIComponent(`Portfolio Contact - ${name.trim()}`);
const subject = encodeURIComponent(`Portfolyo İletişim - ${name.trim()}`);
const body = encodeURIComponent(
`Name: ${name.trim()}\nEmail: ${email.trim()}\n\nMessage:\n${message.trim()}`,
`Ad Soyad: ${name.trim()}\nE-posta: ${email.trim()}\n\nMesaj:\n${message.trim()}`,
);
window.location.href = `mailto:poyrazavsever@gmail.com?subject=${subject}&body=${body}`;
@@ -26,12 +26,12 @@ export function ContactContent() {
<section className="grid gap-3 md:grid-cols-[1fr_1.2fr]">
<Card className="rounded-sm border-border p-4">
<Typography variant="large" className="text-base">
Contact
İletişim
</Typography>
<div className="mt-4 space-y-3">
<div>
<Typography variant="small" className="text-muted-foreground">
E-mail
E-posta
</Typography>
<a
href="mailto:poyrazavsever@gmail.com"
@@ -42,9 +42,9 @@ export function ContactContent() {
</div>
<div>
<Typography variant="small" className="text-muted-foreground">
Response
Dönüş Süresi
</Typography>
<Typography variant="small">Usually within 24 hours.</Typography>
<Typography variant="small">Genelde 24 saat içinde.</Typography>
</div>
</div>
</Card>
@@ -52,42 +52,42 @@ export function ContactContent() {
<Card className="rounded-sm border-border p-4">
<form onSubmit={handleSubmit} className="space-y-3">
<div className="space-y-1.5">
<Label htmlFor="contact-name">Name</Label>
<Label htmlFor="contact-name">Ad Soyad</Label>
<Input
id="contact-name"
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Your name"
placeholder="Adın soyadın"
className="rounded-sm"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="contact-email">Email</Label>
<Label htmlFor="contact-email">E-posta</Label>
<Input
id="contact-email"
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
placeholder="you@example.com"
placeholder="ornek@eposta.com"
className="rounded-sm"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="contact-message">Message</Label>
<Label htmlFor="contact-message">Mesaj</Label>
<Textarea
id="contact-message"
value={message}
onChange={(event) => setMessage(event.target.value)}
placeholder="Write your message..."
placeholder="Mesajını yaz..."
className="min-h-28 rounded-sm"
/>
</div>
<div className="flex justify-end">
<Button type="submit" className="rounded-sm" disabled={!isValid}>
Send
Gönder
</Button>
</div>
</form>
+22 -16
View File
@@ -16,6 +16,12 @@ type ContentContentProps = {
pdfFiles: string[];
};
function getPodcastLabel(podcast: PodcastEpisode["podcast"]) {
if (podcast === "yazilim") return "Yazılım";
if (podcast === "masa-basi") return "Masa Başı";
return podcast;
}
function PdfFirstPagePreview({ src, title }: { src: string; title: string }) {
const canvasRef = useRef<HTMLCanvasElement | null>(null);
const [failed, setFailed] = useState(false);
@@ -83,7 +89,7 @@ function PdfFirstPagePreview({ src, title }: { src: string; title: string }) {
return (
<div className="flex h-full w-full items-center justify-center bg-muted/20 p-2">
<Typography variant="small" className="text-muted-foreground">
Preview unavailable
Önizleme yüklenemedi
</Typography>
</div>
);
@@ -186,14 +192,14 @@ export function ContentContent({
<section className="flex h-full flex-col gap-3 overflow-y-auto">
<section className="grid gap-3 md:grid-cols-2">
<PodcastColumn
title="Poyraz ile Yazilim"
subtitle="Regular schedule, every Sunday."
title="Poyraz ile Yazılım"
subtitle="Düzenli yayın, her pazar."
episodes={yazilimEpisodes}
onOpenEpisode={openEpisode}
/>
<PodcastColumn
title="Poyraz ile Masa Basi"
subtitle="Irregular schedule, guest-focused."
title="Poyraz ile Masa Başı"
subtitle="Düzensiz yayın, konuk odaklı."
episodes={masaBasiEpisodes}
onOpenEpisode={openEpisode}
/>
@@ -201,7 +207,7 @@ export function ContentContent({
<section className="space-y-2">
<Typography variant="large" className="text-base">
Latest YouTube Videos
Son YouTube Videoları
</Typography>
<div className="grid gap-2 md:grid-cols-3">
{embeddedVideos.map((item) => (
@@ -210,7 +216,7 @@ export function ContentContent({
<div className="aspect-video w-full">
<iframe
src={item.embedUrl}
title="YouTube video player"
title="YouTube video oynatıcı"
className="h-full w-full"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
@@ -221,7 +227,7 @@ export function ContentContent({
) : (
<div className="p-3">
<Typography variant="small" className="text-muted-foreground">
Invalid video link.
Geçersiz video bağlantısı.
</Typography>
</div>
)}
@@ -232,7 +238,7 @@ export function ContentContent({
<section className="space-y-2">
<Typography variant="large" className="text-base">
LinkedIn PDF Notes
LinkedIn PDF Notları
</Typography>
<div className="grid gap-2 grid-cols-2 md:grid-cols-3">
{pdfFiles.map((pdf, index) => (
@@ -244,7 +250,7 @@ export function ContentContent({
>
<Card className="overflow-hidden rounded-sm border-border p-0 transition-colors hover:border-zinc-700">
<div className="aspect-square w-full">
<PdfFirstPagePreview src={`/pdf/${pdf}`} title={`${pdf} preview`} />
<PdfFirstPagePreview src={`/pdf/${pdf}`} title={`${pdf} önizleme`} />
</div>
</Card>
</button>
@@ -255,7 +261,7 @@ export function ContentContent({
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
<SheetContent side="right" className="w-full max-w-xl p-0">
<div className="border-b border-border px-4 py-3">
<SheetTitle>{selectedEpisode?.title ?? "Episode"}</SheetTitle>
<SheetTitle>{selectedEpisode?.title ?? "Bölüm"}</SheetTitle>
{selectedEpisode ? (
<Typography variant="small" className="mt-1 text-muted-foreground">
{selectedEpisode.date}
@@ -267,7 +273,7 @@ export function ContentContent({
{selectedEpisode ? (
<>
<div className="flex flex-wrap gap-2">
<Badge className="rounded-sm">{selectedEpisode.podcast}</Badge>
<Badge className="rounded-sm">{getPodcastLabel(selectedEpisode.podcast)}</Badge>
</div>
<div className="flex flex-wrap gap-2">
@@ -321,7 +327,7 @@ export function ContentContent({
<Modal open={pdfModalOpen} onOpenChange={setPdfModalOpen}>
<ModalContent size="xl" className="rounded-sm p-4">
<ModalTitle>{activePdf ? activePdf.replace(/\.pdf$/i, "") : "PDF Note"}</ModalTitle>
<ModalTitle>{activePdf ? activePdf.replace(/\.pdf$/i, "") : "PDF Notu"}</ModalTitle>
<div className="mt-3 flex flex-wrap items-center justify-between gap-2">
<Typography variant="small" className="text-muted-foreground">
@@ -335,7 +341,7 @@ export function ContentContent({
disabled={!canGoPrev}
onClick={() => setActivePdfIndex((prev) => Math.max(0, prev - 1))}
>
Prev
Önceki
</Button>
<Button
type="button"
@@ -344,7 +350,7 @@ export function ContentContent({
disabled={!canGoNext}
onClick={() => setActivePdfIndex((prev) => Math.min(pdfFiles.length - 1, prev + 1))}
>
Next
Sonraki
</Button>
</div>
</div>
@@ -360,7 +366,7 @@ export function ContentContent({
) : (
<Card className="mt-3 rounded-sm border-border p-3">
<Typography variant="small" className="text-muted-foreground">
No PDF found in /public/pdf.
`/public/pdf` içinde PDF bulunamadı.
</Typography>
</Card>
)}
+6 -4
View File
@@ -42,18 +42,20 @@ export function HomeHero() {
))}
</div>
<Card className="grid grid-cols-[112px_1fr] sm:grid-cols-[168px_1fr] items-stretch gap-2 rounded-sm border-border md:h-full">
<Card className="grid grid-cols-[112px_1fr] items-stretch gap-2 rounded-sm border-border sm:grid-cols-[168px_1fr] md:h-full">
<div className="flex flex-col justify-center gap-1 px-3 py-2">
<div className="flex items-center gap-1">
<Typography variant="h2" className="leading-tight">
Poyraz
</Typography>
<Typography variant="h2" secondaryFont className="leading-tight text-red-600">
Avsever
{" "}
Avsever
</Typography>
</div>
<Typography variant="small" className="text-muted-foreground">
Teknolojiyi keşfeden bir genç. Yazılımı seviyor sanırım. Çok fazla şey yapıyor, takip edin.
Teknolojiyi merak eden bir genç. Yazılımı seviyor, bir şeyler üretiyor ve bolca
deniyor. Çok fazla şey yapıyor, takipte kal.
</Typography>
</div>
@@ -68,7 +70,7 @@ export function HomeHero() {
alt="Poyraz Avsever"
width={240}
height={240}
className="absolute right-0 bottom-0 h-auto w-20 md:w-48 object-contain"
className="absolute right-0 bottom-0 h-auto w-20 object-contain md:w-48"
/>
</div>
</div>
+2 -2
View File
@@ -24,7 +24,7 @@ export function HomeVideosSection() {
<div className="aspect-video w-full">
<iframe
src={embedUrl}
title="YouTube video player"
title="YouTube video oynatıcı"
className="h-full w-full"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
@@ -35,7 +35,7 @@ export function HomeVideosSection() {
) : (
<div className="p-3">
<Typography variant="small" className="text-muted-foreground">
Invalid video link.
Geçersiz video bağlantısı.
</Typography>
</div>
)}
+15 -15
View File
@@ -13,9 +13,9 @@ export function NewsletterContent() {
event.preventDefault();
if (!isValid) return;
const subject = encodeURIComponent(`Newsletter Subscription - ${name.trim()}`);
const subject = encodeURIComponent(`Bülten Aboneliği - ${name.trim()}`);
const body = encodeURIComponent(
`Hello,\n\nI want to subscribe to the weekly "Poyraz ile Yazilim" newsletter.\n\nName: ${name.trim()}\nEmail: ${email.trim()}`,
`Merhaba,\n\nHaftalık "Poyraz ile Yazılım" bültenine abone olmak istiyorum.\n\nAd Soyad: ${name.trim()}\nE-posta: ${email.trim()}`,
);
window.location.href = `mailto:poyrazavsever@gmail.com?subject=${subject}&body=${body}`;
@@ -25,30 +25,30 @@ export function NewsletterContent() {
<section className="grid gap-3 md:grid-cols-[1fr_1.2fr]">
<Card className="rounded-sm border-border p-4">
<Typography variant="large" className="text-base">
Weekly Software Newsletter
Haftalık Yazılım Bülteni
</Typography>
<Typography variant="small" className="mt-1 text-muted-foreground">
Mail version of Poyraz ile Yazilim.
Poyraz ile Yazılım&apos;ın e-posta versiyonu.
</Typography>
<div className="mt-4 space-y-3">
<div>
<Typography variant="small" className="text-muted-foreground">
Schedule
Yayın Günü
</Typography>
<Typography variant="small">Every Sunday</Typography>
<Typography variant="small">Her pazar</Typography>
</div>
<div>
<Typography variant="small" className="text-muted-foreground">
What you get
Seni neler bekliyor
</Typography>
<Typography variant="small">Weekly software agenda and practical notes.</Typography>
<Typography variant="small">Haftalık yazılım gündemi ve pratik notlar.</Typography>
</div>
<div>
<Typography variant="small" className="text-muted-foreground">
Delivery
Teslimat
</Typography>
<Typography variant="small">Directly to your inbox.</Typography>
<Typography variant="small">Doğrudan e-posta kutuna.</Typography>
</div>
</div>
</Card>
@@ -56,31 +56,31 @@ export function NewsletterContent() {
<Card className="rounded-sm border-border p-4">
<form onSubmit={handleSubmit} className="space-y-3">
<div className="space-y-1.5">
<Label htmlFor="newsletter-name">Name</Label>
<Label htmlFor="newsletter-name">Ad Soyad</Label>
<Input
id="newsletter-name"
value={name}
onChange={(event) => setName(event.target.value)}
placeholder="Your name"
placeholder="Adın soyadın"
className="rounded-sm"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="newsletter-email">Email</Label>
<Label htmlFor="newsletter-email">E-posta</Label>
<Input
id="newsletter-email"
type="email"
value={email}
onChange={(event) => setEmail(event.target.value)}
placeholder="you@example.com"
placeholder="ornek@eposta.com"
className="rounded-sm"
/>
</div>
<div className="flex justify-end">
<Button type="submit" className="rounded-sm" disabled={!isValid}>
Subscribe
Abone Ol
</Button>
</div>
</form>
+8 -8
View File
@@ -69,7 +69,7 @@ export async function ProjectsContent() {
<div className="overflow-x-auto rounded-sm">
<Image
src="https://ghchart.rshah.org/dc2626/poyrazavsever"
alt="GitHub contribution activity for poyrazavsever"
alt="poyrazavsever için GitHub katkı grafiği"
width={820}
height={120}
className="h-auto w-full min-w-[740px]"
@@ -78,19 +78,19 @@ export async function ProjectsContent() {
</div>
</Card>
<ProjectSection title="Mobile Apps" items={MOBILE_APPS} />
<ProjectSection title="Web Apps" items={WEB_APPS} />
<ProjectSection title="Figma Templates" items={FIGMA_TEMPLATES} />
<ProjectSection title="Mobil Uygulamalar" items={MOBILE_APPS} />
<ProjectSection title="Web Uygulamaları" items={WEB_APPS} />
<ProjectSection title="Figma Şablonları" items={FIGMA_TEMPLATES} />
<section className="space-y-2">
<Typography variant="large" className="text-base">
npm paketleri (@poyrazavsever)
npm Paketleri (@poyrazavsever)
</Typography>
<div className="grid gap-2 md:grid-cols-2">
{npmPackages.length === 0 ? (
<Card className="rounded-sm border-border p-3 md:col-span-2">
<Typography variant="small" className="text-muted-foreground">
npm API response is empty right now.
npm API yanıtı şu anda boş.
</Typography>
</Card>
) : (
@@ -121,13 +121,13 @@ export async function ProjectsContent() {
<section className="space-y-2">
<Typography variant="large" className="text-base">
GitHub Repos (@poyrazavsever)
GitHub Repoları (@poyrazavsever)
</Typography>
<div className="grid gap-2 md:grid-cols-2">
{repos.length === 0 ? (
<Card className="rounded-sm border-border p-3 md:col-span-2">
<Typography variant="small" className="text-muted-foreground">
GitHub API response is empty right now.
GitHub API yanıtı şu anda boş.
</Typography>
</Card>
) : (
+1 -1
View File
@@ -31,7 +31,7 @@ export function ReferenceCards({ className }: ReferenceCardsProps) {
href={item.profileHref}
target="_blank"
rel="noreferrer"
aria-label={`${item.author} LinkedIn profile`}
aria-label={`${item.author} LinkedIn profili`}
className="block"
>
{card}
+1 -1
View File
@@ -8,7 +8,7 @@ export function ReferencesDetailContent() {
href="/about"
className="inline-flex w-fit items-center rounded-sm border border-border px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground"
>
{"<- Back to about"}
{"<- Hakkımda'ya dön"}
</Link>
<ReferenceCards className="flex flex-wrap gap-3" />
+3 -3
View File
@@ -87,12 +87,12 @@ export function SearchCommand({ open, onOpenChange }: SearchCommandProps) {
<CommandPalette open={open} onOpenChange={handleOpenChange}>
<CommandPaletteContent className=" rounded-none p-0 pt-3 w-72 sm:w-full sm:max-w-xl sm:rounded-sm sm:p-0 sm:pt-2">
<CommandPaletteInput
placeholder="Search pages and links..."
placeholder="Sayfa ve bağlantılarda ara..."
className="mt-2 pr-10"
onValueChange={setQuery}
/>
<CommandPaletteList>
<CommandPaletteEmpty>No results found.</CommandPaletteEmpty>
<CommandPaletteEmpty>Sonuç bulunamadı.</CommandPaletteEmpty>
{filteredGroups.map((group, index) => (
<div key={group.id}>
{index > 0 && <CommandPaletteSeparator />}
@@ -112,7 +112,7 @@ export function SearchCommand({ open, onOpenChange }: SearchCommandProps) {
))}
</CommandPaletteList>
<CommandPaletteFooter className="text-xs text-muted-foreground">
Press {shortcut} to open quickly
Hızlıca açmak için {shortcut} kullan
</CommandPaletteFooter>
</CommandPaletteContent>
</CommandPalette>
+12 -12
View File
@@ -46,7 +46,7 @@ const TOP_ICON_LINKS = [
},
{
id: "cv",
label: "CV",
label: "Özgeçmiş",
href: "/resume.pdf",
icon: "mdi:file-account-outline",
external: false,
@@ -91,7 +91,7 @@ export function SiteNavbar() {
</div>
<header className="flex items-center justify-between gap-3 border-b border-border pb-4">
<Link href="/" aria-label="Go to home" className="inline-flex items-center">
<Link href="/" aria-label="Ana sayfaya git" className="inline-flex items-center">
<Avatar className="h-9 w-9 rounded-sm">
<AvatarImage src="/logo/logo.jpeg" alt="Poyraz Avsever" />
<AvatarFallback className="rounded-sm bg-muted text-xs font-semibold">
@@ -101,7 +101,7 @@ export function SiteNavbar() {
</Link>
<div className="hidden items-center gap-3 md:flex">
<nav aria-label="Main navigation">
<nav aria-label="Ana navigasyon">
<ul className="flex items-center gap-3">
{NAV_LINKS.map((item, index) => (
<li key={item.id} className="flex items-center gap-3">
@@ -121,11 +121,11 @@ export function SiteNavbar() {
type="button"
onClick={() => setSearchOpen(true)}
className="inline-flex h-8 w-44 cursor-pointer items-center justify-between rounded-sm border border-border px-2.5 text-sm text-muted-foreground transition-colors hover:text-foreground sm:w-52"
aria-label="Open command palette"
aria-label="Komut paletini aç"
>
<span className="inline-flex items-center gap-2">
<Icon icon="mdi:magnify" width={16} height={16} />
<span>Search</span>
<span>Ara</span>
</span>
<span className="text-xs text-muted-foreground">{shortcut}</span>
</button>
@@ -133,10 +133,10 @@ export function SiteNavbar() {
<DropdownMenu>
<DropdownMenuTrigger className="inline-flex h-8 cursor-pointer items-center gap-2 rounded-sm border border-border px-2.5 text-sm text-muted-foreground transition-colors hover:text-foreground">
<Icon icon="mdi:share-variant" width={16} height={16} />
<span>Social</span>
<span>Sosyal</span>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-52 rounded-sm">
<DropdownMenuLabel>Social Links</DropdownMenuLabel>
<DropdownMenuLabel>Sosyal Bağlantılar</DropdownMenuLabel>
<DropdownMenuSeparator />
{SOCIAL_LINKS.map((item) => (
<DropdownMenuItem key={item.id} asChild>
@@ -159,21 +159,21 @@ export function SiteNavbar() {
<Sheet>
<SheetTrigger className="inline-flex h-8 cursor-pointer items-center gap-2 rounded-sm border border-border px-2.5 text-sm text-muted-foreground transition-colors hover:text-foreground">
<Icon icon="mdi:menu" width={18} height={18} />
<span>Menu</span>
<span>Menü</span>
</SheetTrigger>
<SheetContent side="right" className="w-72 p-4">
<SheetTitle className="sr-only">Mobile Menu</SheetTitle>
<SheetTitle className="sr-only">Mobil Menü</SheetTitle>
<div className="flex flex-col gap-4">
<SheetClose asChild>
<button
type="button"
onClick={() => setSearchOpen(true)}
className="inline-flex h-9 w-full cursor-pointer items-center justify-between rounded-sm border border-border px-3 text-sm text-muted-foreground transition-colors hover:text-foreground"
aria-label="Open command palette"
aria-label="Komut paletini aç"
>
<span className="inline-flex items-center gap-2">
<Icon icon="mdi:magnify" width={16} height={16} />
<span>Search</span>
<span>Ara</span>
</span>
<span className="text-xs text-muted-foreground/80">{shortcut}</span>
</button>
@@ -181,7 +181,7 @@ export function SiteNavbar() {
<Separator className="bg-border" decorative />
<nav aria-label="Mobile navigation">
<nav aria-label="Mobil navigasyon">
<ul className="space-y-2">
{NAV_LINKS.map((item) => (
<li key={item.id}>
+4 -4
View File
@@ -9,7 +9,7 @@ export function VolunteerCommunityContent() {
href="/about"
className="inline-flex w-fit items-center rounded-sm border border-border px-3 py-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground"
>
{"<- Back to about"}
{"<- Hakkımda'ya dön"}
</Link>
<div className="grid gap-3">
@@ -20,12 +20,12 @@ export function VolunteerCommunityContent() {
</Typography>
<Typography variant="small" className="mt-2 text-muted-foreground">
<span className="font-semibold text-foreground">Timeline:</span> {item.timeline}
<span className="font-semibold text-foreground">Zaman Çizelgesi:</span> {item.timeline}
</Typography>
{item.link ? (
<Typography variant="small" className="mt-1 text-muted-foreground">
<span className="font-semibold text-foreground">Link:</span>{" "}
<span className="font-semibold text-foreground">Bağlantı:</span>{" "}
<Link
href={item.link}
target="_blank"
@@ -38,7 +38,7 @@ export function VolunteerCommunityContent() {
) : null}
<Typography variant="small" className="mt-1 text-muted-foreground">
<span className="font-semibold text-foreground">Focus:</span> {item.focus}
<span className="font-semibold text-foreground">Odak:</span> {item.focus}
</Typography>
</Card>
))}
+23 -23
View File
@@ -29,7 +29,7 @@ const navigationItems: CommandPaletteItem[] = NAV_LINKS.map((item) => ({
label: item.label,
href: item.href,
icon: "mdi:compass-outline",
keywords: [item.label, item.href, "page", "navigation"],
keywords: [item.label, item.href, "sayfa", "navigasyon", "page", "navigation"],
}));
const socialItems: CommandPaletteItem[] = SOCIAL_LINKS.map((item) => ({
@@ -38,7 +38,7 @@ const socialItems: CommandPaletteItem[] = SOCIAL_LINKS.map((item) => ({
href: item.href,
icon: item.icon,
external: true,
keywords: [item.label, "social", "profile"],
keywords: [item.label, "sosyal", "profil", "social", "profile"],
}));
const blogItems: CommandPaletteItem[] = [
@@ -47,21 +47,21 @@ const blogItems: CommandPaletteItem[] = [
label: item.title,
href: `/blog/${item.slug}`,
icon: "mdi:post-outline",
keywords: [item.category, item.author, item.excerpt, "blog", "article"],
keywords: [item.category, item.author, item.excerpt, "blog", "yazı", "article"],
})),
...BLOG_ARTICLES.map((item, index) => ({
id: `blog-article-${item.id}-${index}`,
label: item.title,
href: item.href,
icon: "mdi:file-document-outline",
keywords: [item.category, item.excerpt, item.readTime, "blog", "article"],
keywords: [item.category, item.excerpt, item.readTime, "blog", "yazı", "article"],
})),
...BLOG_CATEGORIES.map((item) => ({
id: `blog-category-${item}`,
label: `Category: ${item}`,
label: `Kategori: ${item}`,
href: "/blog",
icon: "mdi:tag-outline",
keywords: [item, "blog", "category"],
keywords: [item, "blog", "kategori", "category"],
})),
];
@@ -71,35 +71,35 @@ const aboutItems: CommandPaletteItem[] = [
label: item.title,
href: "/about",
icon: "mdi:school-outline",
keywords: [item.institution, item.period, item.description, "education", "about"],
keywords: [item.institution, item.period, item.description, "eğitim", "education", "about"],
})),
...EXPERIENCE.map((item) => ({
id: `experience-${item.id}`,
label: item.role,
href: "/about",
icon: "mdi:briefcase-outline",
keywords: [item.company, item.period, "experience", "about"],
keywords: [item.company, item.period, "deneyim", "experience", "about"],
})),
...certificates.map((item, index) => ({
id: `certificate-${index}`,
label: item.name,
href: "/about",
icon: "mdi:certificate-outline",
keywords: [item.organization, item.date, item.category, item.description, "certificate"],
keywords: [item.organization, item.date, item.category, item.description, "sertifika", "certificate"],
})),
...REFERENCES.map((item) => ({
id: `reference-${item.id}`,
label: `Reference: ${item.author}`,
label: `Referans: ${item.author}`,
href: "/about/references",
icon: "mdi:account-voice-outline",
keywords: [item.role, item.quote, "reference", "testimonial"],
keywords: [item.role, item.quote, "referans", "yorum", "reference", "testimonial"],
})),
...VOLUNTEER_COMMUNITY_ITEMS.map((item) => ({
id: `volunteer-${item.id}`,
label: item.title,
href: "/about/volunteer-community",
icon: "mdi:hand-heart-outline",
keywords: [item.timeline, item.focus, item.link ?? "", "volunteer", "community"],
keywords: [item.timeline, item.focus, item.link ?? "", "gönüllülük", "topluluk", "volunteer", "community"],
})),
];
@@ -109,7 +109,7 @@ const projectItems: CommandPaletteItem[] = [
label: item.title,
href: "/projects",
icon: "mdi:cellphone",
keywords: [item.description, item.badge ?? "", "mobile", "project"],
keywords: [item.description, item.badge ?? "", "mobil", "proje", "mobile", "project"],
})),
...WEB_APPS.map((item) => ({
id: `web-project-${item.id}`,
@@ -117,7 +117,7 @@ const projectItems: CommandPaletteItem[] = [
href: item.href ?? "/projects",
icon: "mdi:web",
external: Boolean(item.href),
keywords: [item.description, item.badge ?? "", "web", "project"],
keywords: [item.description, item.badge ?? "", "web", "proje", "project"],
})),
...FIGMA_TEMPLATES.map((item) => ({
id: `figma-project-${item.id}`,
@@ -125,48 +125,48 @@ const projectItems: CommandPaletteItem[] = [
href: item.href ?? "/projects",
icon: "mdi:figma",
external: Boolean(item.href),
keywords: [item.description, item.badge ?? "", "figma", "template"],
keywords: [item.description, item.badge ?? "", "figma", "şablon", "template"],
})),
];
const contentItems: CommandPaletteItem[] = YOUTUBE_VIDEO_LINKS.map((item, index) => ({
id: `youtube-video-${index + 1}`,
label: `YouTube Video ${index + 1}`,
label: `YouTube Videosu ${index + 1}`,
href: item,
icon: "mdi:youtube",
external: true,
keywords: [item, "youtube", "video", "content"],
keywords: [item, "youtube", "video", "içerik", "content"],
}));
export const COMMAND_PALETTE_GROUPS: CommandPaletteGroup[] = [
{
id: "navigation",
heading: "Navigation",
heading: "Sayfalar",
items: navigationItems,
},
{
id: "blog-data",
heading: "Blog Data",
heading: "Blog İçerikleri",
items: blogItems,
},
{
id: "about-data",
heading: "About Data",
heading: "Hakkımda",
items: aboutItems,
},
{
id: "projects-data",
heading: "Projects Data",
heading: "Projeler",
items: projectItems,
},
{
id: "content-data",
heading: "Content Data",
heading: "İçerikler",
items: contentItems,
},
{
id: "social",
heading: "Social",
heading: "Sosyal",
items: socialItems,
},
] as const;
+1 -1
View File
@@ -41,7 +41,7 @@ async function readPodcastEpisodes(kind: PodcastKind): Promise<PodcastEpisode[]>
return {
slug: file.replace(/\.md$/, ""),
title: data.title ?? "Untitled Episode",
title: data.title ?? "Başlıksız Bölüm",
date: data.date ?? "1970-01-01",
youtubeUrl: data.youtubeUrl ?? "",
spotifyUrl: data.spotifyUrl ?? "",
+7 -8
View File
@@ -1,17 +1,16 @@
export const NAV_LINKS = [
{ id: "home", label: "Home", href: "/" },
{ id: "about", label: "About", href: "/about" },
{ id: "about", label: "Hakkımda", href: "/about" },
{ id: "blog", label: "Blog", href: "/blog" },
{ id: "content", label: "Content", href: "/content" },
{ id: "newsletter", label: "Newsletter", href: "/newsletter" },
{ id: "projects", label: "Projects", href: "/projects" },
{ id: "contact", label: "Contact", href: "/contact" },
{ id: "content", label: "İçerikler", href: "/content" },
{ id: "newsletter", label: "Bülten", href: "/newsletter" },
{ id: "projects", label: "Projeler", href: "/projects" },
{ id: "contact", label: "İletişim", href: "/contact" },
] as const;
export const SOCIAL_LINKS = [
{
id: "email",
label: "E-Mail",
label: "E-posta",
href: "mailto:poyrazavsever@gmail.com",
icon: "mdi:email",
},
@@ -65,7 +64,7 @@ export const SOCIAL_LINKS = [
},
{
id: "buy-me-a-coffee",
label: "Buy Me a Coffee",
label: "Bana kahve ısmarla",
href: "https://buymeacoffee.com/poyrazavsever",
icon: "mdi:coffee",
},