feat(i18n): setup next-intl core config and translation dictionaries
This commit is contained in:
+7
-90
@@ -1,94 +1,11 @@
|
|||||||
import type { Metadata } from "next";
|
import { ReactNode } from "react";
|
||||||
import "./globals.css";
|
|
||||||
|
|
||||||
import { AppShell } from "@/components/app-shell";
|
type Props = {
|
||||||
import { GoogleAnalytics } from "@/components/google-analytics";
|
children: ReactNode;
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
|
||||||
metadataBase: new URL("https://poyrazavsever.com"),
|
|
||||||
title: {
|
|
||||||
default: "Poyraz Avsever | Portfolyo",
|
|
||||||
template: "%s | Poyraz Avsever",
|
|
||||||
},
|
|
||||||
description:
|
|
||||||
"Poyraz Avsever'in projelerini, yazılım içeriklerini ve teknik çalışmalarını paylaştığı kişisel portfolyo sitesi.",
|
|
||||||
applicationName: "Poyraz Avsever Portfolyo",
|
|
||||||
alternates: {
|
|
||||||
canonical: "/",
|
|
||||||
},
|
|
||||||
icons: {
|
|
||||||
icon: [
|
|
||||||
{ url: "/favicon.ico", sizes: "any" },
|
|
||||||
{ url: "/logo/logo.jpeg", type: "image/jpeg" },
|
|
||||||
],
|
|
||||||
shortcut: "/favicon.ico",
|
|
||||||
apple: "/logo/logo.jpeg",
|
|
||||||
},
|
|
||||||
authors: [{ name: "Poyraz Avsever" }],
|
|
||||||
creator: "Poyraz Avsever",
|
|
||||||
publisher: "Poyraz Avsever",
|
|
||||||
openGraph: {
|
|
||||||
type: "website",
|
|
||||||
locale: "tr_TR",
|
|
||||||
url: "https://poyrazavsever.com",
|
|
||||||
siteName: "Poyraz Avsever Portfolyo",
|
|
||||||
title: "Poyraz Avsever | Portfolyo",
|
|
||||||
description:
|
|
||||||
"Poyraz Avsever'in projelerini, yazılım içeriklerini ve teknik çalışmalarını paylaştığı kişisel portfolyo sitesi.",
|
|
||||||
images: [
|
|
||||||
{
|
|
||||||
url: "/logo/logo.jpeg",
|
|
||||||
width: 1200,
|
|
||||||
height: 1200,
|
|
||||||
alt: "Poyraz Avsever Logo",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
twitter: {
|
|
||||||
card: "summary_large_image",
|
|
||||||
title: "Poyraz Avsever | Portfolyo",
|
|
||||||
description:
|
|
||||||
"Poyraz Avsever'in projelerini, yazılım içeriklerini ve teknik çalışmalarını paylaştığı kişisel portfolyo sitesi.",
|
|
||||||
images: ["/logo/logo.jpeg"],
|
|
||||||
creator: "@poyrazavsever",
|
|
||||||
},
|
|
||||||
keywords: [
|
|
||||||
"Poyraz Avsever",
|
|
||||||
"Portfolio",
|
|
||||||
"Freelancer",
|
|
||||||
"Fullstack Developer",
|
|
||||||
"Web Developer",
|
|
||||||
"Projects",
|
|
||||||
"Skills",
|
|
||||||
"Services",
|
|
||||||
"Coding",
|
|
||||||
"Technology",
|
|
||||||
"Personal Website",
|
|
||||||
"Software Engineer",
|
|
||||||
"Frontend Developer",
|
|
||||||
"Backend Developer",
|
|
||||||
"JavaScript",
|
|
||||||
"React",
|
|
||||||
"Node.js",
|
|
||||||
"Next.js",
|
|
||||||
"Web Development",
|
|
||||||
"Programming",
|
|
||||||
"Tech Enthusiast",
|
|
||||||
"Developer Portfolio",
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
// Since we have a `[locale]` layout, this layout is just a placeholder
|
||||||
children,
|
// that passes children through.
|
||||||
}: Readonly<{
|
export default function RootLayout({ children }: Props) {
|
||||||
children: React.ReactNode;
|
return children;
|
||||||
}>) {
|
|
||||||
return (
|
|
||||||
<html lang="tr">
|
|
||||||
<body className="min-h-dvh bg-background text-foreground antialiased">
|
|
||||||
<GoogleAnalytics />
|
|
||||||
<AppShell>{children}</AppShell>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
import {getRequestConfig} from "next-intl/server";
|
||||||
|
import {routing} from "./routing";
|
||||||
|
|
||||||
|
export default getRequestConfig(async ({requestLocale}) => {
|
||||||
|
let locale = await requestLocale;
|
||||||
|
|
||||||
|
if (!locale || !routing.locales.includes(locale as "tr" | "en")) {
|
||||||
|
locale = routing.defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
locale,
|
||||||
|
messages: (await import(`../messages/${locale}.json`)).default
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import {defineRouting} from "next-intl/routing";
|
||||||
|
import {createNavigation} from "next-intl/navigation";
|
||||||
|
|
||||||
|
export const routing = defineRouting({
|
||||||
|
locales: ["tr", "en"],
|
||||||
|
defaultLocale: "tr",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const {Link, redirect, usePathname, useRouter, getPathname} =
|
||||||
|
createNavigation(routing);
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"Nav": {
|
||||||
|
"about": "About",
|
||||||
|
"blog": "Blog",
|
||||||
|
"content": "Content",
|
||||||
|
"projects": "Projects",
|
||||||
|
"gallery": "Gallery",
|
||||||
|
"contact": "Contact",
|
||||||
|
"search": "Search",
|
||||||
|
"social": "Social",
|
||||||
|
"socialLinks": "Social Links",
|
||||||
|
"menu": "Menu",
|
||||||
|
"mobileMenu": "Mobile Menu",
|
||||||
|
"resume": "Resume"
|
||||||
|
},
|
||||||
|
"Home": {
|
||||||
|
"role": "A young mind curious about technology. Following developments in software development, AI, and the tech world.",
|
||||||
|
"sections": {
|
||||||
|
"recentPosts": "Recent Posts",
|
||||||
|
"references": "References",
|
||||||
|
"videos": "Videos",
|
||||||
|
"sponsors": "Sponsors"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"About": {
|
||||||
|
"aboutText": "Ever since I met software in middle school, I've been constantly learning and improving. My passion for learning grew in high school, where I explored different web development technologies. Near the end of high school, I stepped into the mobile world. Today, I actively build, develop, and most importantly, I am still learning.",
|
||||||
|
"allCertificates": "All Certificates",
|
||||||
|
"referencesTitle": "References",
|
||||||
|
"referencesDesc": "View all references on a separate detail page.",
|
||||||
|
"volunteerTitle": "Volunteering & Community",
|
||||||
|
"volunteerDesc": "Inspect timeline and contribution details on a separate page.",
|
||||||
|
"bookmarksTitle": "Bookmarks",
|
||||||
|
"bookmarksDesc": "View quick access links inside a sheet.",
|
||||||
|
"timelineLabel": "Timeline:",
|
||||||
|
"linkLabel": "Link:",
|
||||||
|
"focusLabel": "Focus:",
|
||||||
|
"backToAbout": "<- Back to About"
|
||||||
|
},
|
||||||
|
"Projects": {
|
||||||
|
"sections": {
|
||||||
|
"mobileApps": "Mobile Apps",
|
||||||
|
"webApps": "Web Applications",
|
||||||
|
"extensions": "Extensions",
|
||||||
|
"figmaTemplates": "Figma Designs",
|
||||||
|
"npmPackages": "npm Packages (@poyrazavsever)",
|
||||||
|
"githubRepos": "GitHub Repositories (@poyrazavsever)"
|
||||||
|
},
|
||||||
|
"emptyNpm": "npm API response is currently empty.",
|
||||||
|
"emptyGithub": "GitHub API response is currently empty."
|
||||||
|
},
|
||||||
|
"Blog": {
|
||||||
|
"recentPosts": "Recent Posts",
|
||||||
|
"searchPlaceholder": "Search posts...",
|
||||||
|
"noPosts": "No posts found.",
|
||||||
|
"categories": "Categories",
|
||||||
|
"readTime": "min read",
|
||||||
|
"backToBlog": "<- Back to Blog",
|
||||||
|
"results": "results",
|
||||||
|
"clear": "Clear",
|
||||||
|
"clearFilters": "Clear Filters",
|
||||||
|
"empty": "No blog posts yet.",
|
||||||
|
"emptyCategory": "No blog posts in \"{category}\" category yet.",
|
||||||
|
"noSearch": "No results found for \"{search}\".",
|
||||||
|
"comments": "Comments",
|
||||||
|
"toc": "Table of Contents",
|
||||||
|
"diagramLoading": "Diagram rendering...",
|
||||||
|
"diagramError": "Could not render Mermaid diagram."
|
||||||
|
},
|
||||||
|
"Links": {
|
||||||
|
"desc": "Here you can find all my social accounts, portfolio pages, and quick access links in one place. Open and share directly.",
|
||||||
|
"allLinks": "All Links",
|
||||||
|
"allLinksDesc": "Pages, resources, and social profiles",
|
||||||
|
"selectCategory": "Select category",
|
||||||
|
"allCategories": "All categories",
|
||||||
|
"searchPlaceholder": "Search links... github, medium, /blog",
|
||||||
|
"empty": "No links found matching the selected filter.",
|
||||||
|
"categories": {
|
||||||
|
"navigation": "Pages",
|
||||||
|
"social": "Social",
|
||||||
|
"resources": "Resources"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gallery": {
|
||||||
|
"empty": "No images added to the gallery yet.",
|
||||||
|
"close": "Close",
|
||||||
|
"prev": "Previous",
|
||||||
|
"next": "Next"
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"title": "Poyraz Avsever | Portfolio",
|
||||||
|
"titleTemplate": "%s | Poyraz Avsever",
|
||||||
|
"description": "Poyraz Avsever's personal portfolio website sharing projects, software content, and technical works."
|
||||||
|
},
|
||||||
|
"SearchCommand": {
|
||||||
|
"placeholder": "Search pages and links...",
|
||||||
|
"empty": "No results found.",
|
||||||
|
"footer": "Press {shortcut} to open quickly"
|
||||||
|
},
|
||||||
|
"Content": {
|
||||||
|
"youtubeTitle": "Latest YouTube Videos",
|
||||||
|
"youtubeEmbedTitle": "YouTube video player",
|
||||||
|
"pdfTitle": "LinkedIn PDF Notes",
|
||||||
|
"pdfPreviewError": "Preview could not be loaded",
|
||||||
|
"pdfPreviewTitle": "{name} preview",
|
||||||
|
"pdfModalDefaultTitle": "PDF Note",
|
||||||
|
"prev": "Previous",
|
||||||
|
"next": "Next",
|
||||||
|
"pdfNotFound": "No PDF files found inside `/public/pdf`."
|
||||||
|
},
|
||||||
|
"Contact": {
|
||||||
|
"email": "Email",
|
||||||
|
"linkedin": "LinkedIn",
|
||||||
|
"instagram": "Instagram"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
{
|
||||||
|
"Nav": {
|
||||||
|
"about": "Hakkımda",
|
||||||
|
"blog": "Blog",
|
||||||
|
"content": "İçerikler",
|
||||||
|
"projects": "Projeler",
|
||||||
|
"gallery": "Galeri",
|
||||||
|
"contact": "İletişim",
|
||||||
|
"search": "Ara",
|
||||||
|
"social": "Sosyal",
|
||||||
|
"socialLinks": "Sosyal Bağlantılar",
|
||||||
|
"menu": "Menü",
|
||||||
|
"mobileMenu": "Mobil Menü",
|
||||||
|
"resume": "Özgeçmiş"
|
||||||
|
},
|
||||||
|
"Home": {
|
||||||
|
"role": "Teknolojiyi merak eden bir genç. Yazılım geliştirme, yapay zeka ve teknoloji dünyasındaki gelişmeleri takip ediyor.",
|
||||||
|
"sections": {
|
||||||
|
"recentPosts": "Son Yazılar",
|
||||||
|
"references": "Referanslar",
|
||||||
|
"videos": "Videolar",
|
||||||
|
"sponsors": "Sponsorlar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"About": {
|
||||||
|
"aboutText": "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.",
|
||||||
|
"allCertificates": "Tüm Sertifikalar",
|
||||||
|
"referencesTitle": "Referanslar",
|
||||||
|
"referencesDesc": "Tüm referansları ayrı bir detay sayfasında görüntüle.",
|
||||||
|
"volunteerTitle": "Gönüllülük ve Topluluk",
|
||||||
|
"volunteerDesc": "Zaman çizelgesi ve katkı detaylarını ayrı bir detay sayfasında incele.",
|
||||||
|
"bookmarksTitle": "Yer İmleri",
|
||||||
|
"bookmarksDesc": "Hızlı erişim bağlantılarını bir sheet içinde görüntüle.",
|
||||||
|
"timelineLabel": "Zaman Çizelgesi:",
|
||||||
|
"linkLabel": "Bağlantı:",
|
||||||
|
"focusLabel": "Odak:",
|
||||||
|
"backToAbout": "<- Hakkımda'ya dön"
|
||||||
|
},
|
||||||
|
"Projects": {
|
||||||
|
"sections": {
|
||||||
|
"mobileApps": "Mobil Uygulamalar",
|
||||||
|
"webApps": "Web Uygulamaları",
|
||||||
|
"extensions": "Extension'lar",
|
||||||
|
"figmaTemplates": "Figma Tasarımları",
|
||||||
|
"npmPackages": "npm Paketleri (@poyrazavsever)",
|
||||||
|
"githubRepos": "GitHub Repoları (@poyrazavsever)"
|
||||||
|
},
|
||||||
|
"emptyNpm": "npm API yanıtı şu anda boş.",
|
||||||
|
"emptyGithub": "GitHub API yanıtı şu anda boş."
|
||||||
|
},
|
||||||
|
"Blog": {
|
||||||
|
"recentPosts": "Son Yazılar",
|
||||||
|
"searchPlaceholder": "Yazılarda ara...",
|
||||||
|
"noPosts": "Eşleşen yazı bulunamadı.",
|
||||||
|
"categories": "Kategoriler",
|
||||||
|
"readTime": "dk okuma",
|
||||||
|
"backToBlog": "<- Blog'a dön",
|
||||||
|
"results": "sonuç",
|
||||||
|
"clear": "Temizle",
|
||||||
|
"clearFilters": "Filtreleri Temizle",
|
||||||
|
"empty": "Henüz blog yazısı bulunmuyor.",
|
||||||
|
"emptyCategory": "\"{category}\" kategorisinde henüz blog yazısı bulunmuyor.",
|
||||||
|
"noSearch": "\"{search}\" aramasına uygun sonuç bulunamadı.",
|
||||||
|
"comments": "Yorumlar",
|
||||||
|
"toc": "İçindekiler",
|
||||||
|
"diagramLoading": "Diyagram hazırlanıyor...",
|
||||||
|
"diagramError": "Mermaid diyagramı oluşturulamadı."
|
||||||
|
},
|
||||||
|
"Links": {
|
||||||
|
"desc": "Burada sosyal hesaplarım, portfolyo sayfalarım ve hızlı erişim linklerimin tamamı tek yerde duruyor. Direkt açıp paylaşabilirsin.",
|
||||||
|
"allLinks": "Tüm Linkler",
|
||||||
|
"allLinksDesc": "Sayfalar, kaynaklar ve sosyal profiller",
|
||||||
|
"selectCategory": "Kategori seç",
|
||||||
|
"allCategories": "Tüm kategoriler",
|
||||||
|
"searchPlaceholder": "Link ara... github, medium, /blog",
|
||||||
|
"empty": "Seçili filtreye uygun link bulunamadı.",
|
||||||
|
"categories": {
|
||||||
|
"navigation": "Sayfalar",
|
||||||
|
"social": "Sosyal",
|
||||||
|
"resources": "Kaynaklar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Gallery": {
|
||||||
|
"empty": "Henüz galeriye görsel eklenmemiş.",
|
||||||
|
"close": "Kapat",
|
||||||
|
"prev": "Önceki",
|
||||||
|
"next": "Sonraki"
|
||||||
|
},
|
||||||
|
"Metadata": {
|
||||||
|
"title": "Poyraz Avsever | Portfolyo",
|
||||||
|
"titleTemplate": "%s | Poyraz Avsever",
|
||||||
|
"description": "Poyraz Avsever'in projelerini, yazılım içeriklerini ve teknik çalışmalarını paylaştığı kişisel portfolyo sitesi."
|
||||||
|
},
|
||||||
|
"SearchCommand": {
|
||||||
|
"placeholder": "Sayfa ve bağlantılarda ara...",
|
||||||
|
"empty": "Sonuç bulunamadı.",
|
||||||
|
"footer": "Hızlıca açmak için {shortcut} kullan"
|
||||||
|
},
|
||||||
|
"Content": {
|
||||||
|
"youtubeTitle": "Son YouTube Videoları",
|
||||||
|
"youtubeEmbedTitle": "YouTube video oynatıcı",
|
||||||
|
"pdfTitle": "LinkedIn PDF Notları",
|
||||||
|
"pdfPreviewError": "Önizleme yüklenemedi",
|
||||||
|
"pdfPreviewTitle": "{name} önizleme",
|
||||||
|
"pdfModalDefaultTitle": "PDF Notu",
|
||||||
|
"prev": "Önceki",
|
||||||
|
"next": "Sonraki",
|
||||||
|
"pdfNotFound": "/public/pdf içinde PDF bulunamadı."
|
||||||
|
},
|
||||||
|
"Contact": {
|
||||||
|
"email": "E-posta",
|
||||||
|
"linkedin": "LinkedIn",
|
||||||
|
"instagram": "Instagram"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import createMiddleware from "next-intl/middleware";
|
||||||
|
import {routing} from "./i18n/routing";
|
||||||
|
|
||||||
|
export default createMiddleware(routing);
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
// Match only internationalized pathnames
|
||||||
|
matcher: ["/", "/(tr|en)/:path*", "/((?!_next|_vercel|.*\\..*).*)"]
|
||||||
|
};
|
||||||
+4
-1
@@ -1,4 +1,7 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
import createNextIntlPlugin from "next-intl/plugin";
|
||||||
|
|
||||||
|
const withNextIntl = createNextIntlPlugin();
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
compress: true,
|
compress: true,
|
||||||
@@ -18,4 +21,4 @@ const nextConfig: NextConfig = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default withNextIntl(nextConfig);
|
||||||
|
|||||||
Reference in New Issue
Block a user