📝Update breadcrumbs i18n
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { Breadcrumbs } from '@/components/layout/Breadcrumbs'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
export default function AboutBreadcrumb() {
|
||||
const t = useTranslations('Breadcrumbs')
|
||||
|
||||
return (
|
||||
<Breadcrumbs
|
||||
items={[
|
||||
{
|
||||
label: 'Despre',
|
||||
label: t('about'),
|
||||
href: '/about',
|
||||
current: true,
|
||||
},
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Breadcrumbs } from '@/components/layout/Breadcrumbs'
|
||||
import { getPostBySlug } from '@/lib/markdown'
|
||||
import { getTranslations } from 'next-intl/server'
|
||||
|
||||
interface BreadcrumbItem {
|
||||
label: string
|
||||
@@ -7,28 +8,19 @@ interface BreadcrumbItem {
|
||||
current?: boolean
|
||||
}
|
||||
|
||||
function formatDirectoryName(name: string): string {
|
||||
const directoryNames: { [key: string]: string } = {
|
||||
tech: 'Tehnologie',
|
||||
design: 'Design',
|
||||
tutorial: 'Tutoriale',
|
||||
}
|
||||
|
||||
return directoryNames[name] || name.charAt(0).toUpperCase() + name.slice(1)
|
||||
}
|
||||
|
||||
export default async function BlogPostBreadcrumb({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string[] }>
|
||||
}) {
|
||||
const t = await getTranslations('Breadcrumbs')
|
||||
const { slug } = await params
|
||||
const slugPath = slug.join('/')
|
||||
const post = await getPostBySlug(slugPath)
|
||||
|
||||
const items: BreadcrumbItem[] = [
|
||||
{
|
||||
label: 'Blog',
|
||||
label: t('blog'),
|
||||
href: '/blog',
|
||||
},
|
||||
]
|
||||
@@ -36,8 +28,9 @@ export default async function BlogPostBreadcrumb({
|
||||
if (slug.length > 1) {
|
||||
for (let i = 0; i < slug.length - 1; i++) {
|
||||
const segmentPath = slug.slice(0, i + 1).join('/')
|
||||
const dirName = slug[i]
|
||||
items.push({
|
||||
label: formatDirectoryName(slug[i]),
|
||||
label: t(dirName) || dirName.charAt(0).toUpperCase() + dirName.slice(1),
|
||||
href: `/blog/${segmentPath}`,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { Breadcrumbs } from '@/components/layout/Breadcrumbs'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
export default function BlogBreadcrumb() {
|
||||
const t = useTranslations('Breadcrumbs')
|
||||
|
||||
return (
|
||||
<Breadcrumbs
|
||||
items={[
|
||||
{
|
||||
label: 'Blog',
|
||||
label: t('blog'),
|
||||
href: '/blog',
|
||||
current: true,
|
||||
},
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Breadcrumbs } from '@/components/layout/Breadcrumbs'
|
||||
import { getTranslations } from 'next-intl/server'
|
||||
|
||||
export default async function TagBreadcrumb({ params }: { params: Promise<{ tag: string }> }) {
|
||||
const t = await getTranslations('Breadcrumbs')
|
||||
const { tag } = await params
|
||||
const tagName = tag
|
||||
.split('-')
|
||||
@@ -11,7 +13,7 @@ export default async function TagBreadcrumb({ params }: { params: Promise<{ tag:
|
||||
<Breadcrumbs
|
||||
items={[
|
||||
{
|
||||
label: 'Tag-uri',
|
||||
label: t('tags'),
|
||||
href: '/tags',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { Breadcrumbs } from '@/components/layout/Breadcrumbs'
|
||||
import { useTranslations } from 'next-intl'
|
||||
|
||||
export default function TagsBreadcrumb() {
|
||||
const t = useTranslations('Breadcrumbs')
|
||||
|
||||
return (
|
||||
<Breadcrumbs
|
||||
items={[
|
||||
{
|
||||
label: 'Tag-uri',
|
||||
label: t('tags'),
|
||||
href: '/tags',
|
||||
current: true,
|
||||
},
|
||||
|
||||
@@ -13,7 +13,7 @@ export default async function HomePage({ params }: Props) {
|
||||
const { locale } = await params
|
||||
setRequestLocale(locale)
|
||||
const t = await getTranslations('Home')
|
||||
const tNav = await getTranslations('Navigation')
|
||||
// const tNav = await getTranslations('Navigation')
|
||||
|
||||
const allPosts = await getAllPosts()
|
||||
const featuredPosts = allPosts.slice(0, 6)
|
||||
@@ -29,11 +29,7 @@ export default async function HomePage({ params }: Props) {
|
||||
<div className="relative z-10 max-w-5xl mx-auto px-6 w-full">
|
||||
<div className="border-4 border-slate-300 dark:border-slate-700 bg-white/80 dark:bg-slate-900/80 p-8 md:p-12 transition-colors duration-300">
|
||||
{/* Logo */}
|
||||
<HeroHeader
|
||||
terminalVersion={t('terminalVersion')}
|
||||
blogLabel={tNav('blog')}
|
||||
aboutLabel={tNav('about')}
|
||||
/>
|
||||
<HeroHeader />
|
||||
|
||||
<div className="border-l-4 border-cyan-700 dark:border-cyan-900 pl-6 mb-8">
|
||||
<p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2">
|
||||
|
||||
145
app/globals.css
145
app/globals.css
@@ -473,12 +473,62 @@
|
||||
@layer utilities {
|
||||
.glitch-btn-cyber {
|
||||
--glitch-shimmy: 5;
|
||||
--glitch-clip-1: polygon(0 2%, 100% 2%, 100% 95%, 95% 95%, 95% 90%, 85% 90%, 85% 95%, 8% 95%, 0 70%);
|
||||
--glitch-clip-2: polygon(0 78%, 100% 78%, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 78%);
|
||||
--glitch-clip-3: polygon(0 44%, 100% 44%, 100% 54%, 95% 54%, 95% 54%, 85% 54%, 85% 54%, 8% 54%, 0 54%);
|
||||
--glitch-clip-1: polygon(
|
||||
0 2%,
|
||||
100% 2%,
|
||||
100% 95%,
|
||||
95% 95%,
|
||||
95% 90%,
|
||||
85% 90%,
|
||||
85% 95%,
|
||||
8% 95%,
|
||||
0 70%
|
||||
);
|
||||
--glitch-clip-2: polygon(
|
||||
0 78%,
|
||||
100% 78%,
|
||||
100% 100%,
|
||||
95% 100%,
|
||||
95% 90%,
|
||||
85% 90%,
|
||||
85% 100%,
|
||||
8% 100%,
|
||||
0 78%
|
||||
);
|
||||
--glitch-clip-3: polygon(
|
||||
0 44%,
|
||||
100% 44%,
|
||||
100% 54%,
|
||||
95% 54%,
|
||||
95% 54%,
|
||||
85% 54%,
|
||||
85% 54%,
|
||||
8% 54%,
|
||||
0 54%
|
||||
);
|
||||
--glitch-clip-4: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0);
|
||||
--glitch-clip-5: polygon(0 40%, 100% 40%, 100% 85%, 95% 85%, 95% 85%, 85% 85%, 85% 85%, 8% 85%, 0 70%);
|
||||
--glitch-clip-6: polygon(0 63%, 100% 63%, 100% 80%, 95% 80%, 95% 80%, 85% 80%, 85% 80%, 8% 80%, 0 70%);
|
||||
--glitch-clip-5: polygon(
|
||||
0 40%,
|
||||
100% 40%,
|
||||
100% 85%,
|
||||
95% 85%,
|
||||
95% 85%,
|
||||
85% 85%,
|
||||
85% 85%,
|
||||
8% 85%,
|
||||
0 70%
|
||||
);
|
||||
--glitch-clip-6: polygon(
|
||||
0 63%,
|
||||
100% 63%,
|
||||
100% 80%,
|
||||
95% 80%,
|
||||
95% 80%,
|
||||
85% 80%,
|
||||
85% 80%,
|
||||
8% 80%,
|
||||
0 70%
|
||||
);
|
||||
}
|
||||
|
||||
.glitch-overlay {
|
||||
@@ -498,29 +548,80 @@
|
||||
}
|
||||
|
||||
@keyframes glitch-btn-animate {
|
||||
0% { clip-path: var(--glitch-clip-1); }
|
||||
2%, 8% { clip-path: var(--glitch-clip-2); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); }
|
||||
6% { clip-path: var(--glitch-clip-2); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); }
|
||||
9% { clip-path: var(--glitch-clip-2); transform: translate(0, 0); }
|
||||
10% { clip-path: var(--glitch-clip-3); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); }
|
||||
13% { clip-path: var(--glitch-clip-3); transform: translate(0, 0); }
|
||||
14%, 21% { clip-path: var(--glitch-clip-4); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); }
|
||||
25%, 30% { clip-path: var(--glitch-clip-5); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); }
|
||||
35%, 45% { clip-path: var(--glitch-clip-6); transform: translate(calc(var(--glitch-shimmy) * -1%), 0); }
|
||||
40% { clip-path: var(--glitch-clip-6); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); }
|
||||
50% { clip-path: var(--glitch-clip-6); transform: translate(0, 0); }
|
||||
55% { clip-path: var(--glitch-clip-3); transform: translate(calc(var(--glitch-shimmy) * 1%), 0); }
|
||||
60% { clip-path: var(--glitch-clip-3); transform: translate(0, 0); }
|
||||
61%, 100% { clip-path: var(--glitch-clip-4); }
|
||||
0% {
|
||||
clip-path: var(--glitch-clip-1);
|
||||
}
|
||||
2%,
|
||||
8% {
|
||||
clip-path: var(--glitch-clip-2);
|
||||
transform: translate(calc(var(--glitch-shimmy) * -1%), 0);
|
||||
}
|
||||
6% {
|
||||
clip-path: var(--glitch-clip-2);
|
||||
transform: translate(calc(var(--glitch-shimmy) * 1%), 0);
|
||||
}
|
||||
9% {
|
||||
clip-path: var(--glitch-clip-2);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
10% {
|
||||
clip-path: var(--glitch-clip-3);
|
||||
transform: translate(calc(var(--glitch-shimmy) * 1%), 0);
|
||||
}
|
||||
13% {
|
||||
clip-path: var(--glitch-clip-3);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
14%,
|
||||
21% {
|
||||
clip-path: var(--glitch-clip-4);
|
||||
transform: translate(calc(var(--glitch-shimmy) * 1%), 0);
|
||||
}
|
||||
25%,
|
||||
30% {
|
||||
clip-path: var(--glitch-clip-5);
|
||||
transform: translate(calc(var(--glitch-shimmy) * -1%), 0);
|
||||
}
|
||||
35%,
|
||||
45% {
|
||||
clip-path: var(--glitch-clip-6);
|
||||
transform: translate(calc(var(--glitch-shimmy) * -1%), 0);
|
||||
}
|
||||
40% {
|
||||
clip-path: var(--glitch-clip-6);
|
||||
transform: translate(calc(var(--glitch-shimmy) * 1%), 0);
|
||||
}
|
||||
50% {
|
||||
clip-path: var(--glitch-clip-6);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
55% {
|
||||
clip-path: var(--glitch-clip-3);
|
||||
transform: translate(calc(var(--glitch-shimmy) * 1%), 0);
|
||||
}
|
||||
60% {
|
||||
clip-path: var(--glitch-clip-3);
|
||||
transform: translate(0, 0);
|
||||
}
|
||||
61%,
|
||||
100% {
|
||||
clip-path: var(--glitch-clip-4);
|
||||
}
|
||||
}
|
||||
|
||||
.glitch-btn-subtle {
|
||||
--glitch-shimmy: 2;
|
||||
}
|
||||
|
||||
.glitch-overlay-pink { color: var(--neon-pink); }
|
||||
.glitch-overlay-purple { color: var(--neon-purple); }
|
||||
.glitch-overlay-magenta { color: var(--neon-magenta); }
|
||||
.glitch-overlay-pink {
|
||||
color: var(--neon-pink);
|
||||
}
|
||||
.glitch-overlay-purple {
|
||||
color: var(--neon-purple);
|
||||
}
|
||||
.glitch-overlay-magenta {
|
||||
color: var(--neon-magenta);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.glitch-btn-cyber:is(:hover, :focus-visible) .glitch-overlay {
|
||||
|
||||
@@ -19,11 +19,7 @@ export function GlitchButton({
|
||||
...props
|
||||
}: GlitchButtonProps) {
|
||||
const glitchClasses = !disabled
|
||||
? cn(
|
||||
'glitch-btn-cyber',
|
||||
variant === 'subtle' && 'glitch-btn-subtle',
|
||||
'relative'
|
||||
)
|
||||
? cn('glitch-btn-cyber', variant === 'subtle' && 'glitch-btn-subtle', 'relative')
|
||||
: ''
|
||||
|
||||
const overlayColorClass = {
|
||||
@@ -34,18 +30,11 @@ export function GlitchButton({
|
||||
}[glitchColor]
|
||||
|
||||
return (
|
||||
<button
|
||||
className={cn(glitchClasses, className)}
|
||||
disabled={disabled}
|
||||
{...props}
|
||||
>
|
||||
<button className={cn(glitchClasses, className)} disabled={disabled} {...props}>
|
||||
{children}
|
||||
|
||||
{!disabled && (
|
||||
<div
|
||||
className={cn('glitch-overlay', overlayColorClass)}
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div className={cn('glitch-overlay', overlayColorClass)} aria-hidden="true">
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -5,17 +5,20 @@ import { Link } from '@/i18n/navigation'
|
||||
import Image from 'next/image'
|
||||
import { ThemeToggle } from '@/components/theme-toggle'
|
||||
import { GlitchButton } from '@/components/effects/glitch-button'
|
||||
import LanguageSwitcher from './LanguageSwitcher'
|
||||
import { useLocale, useTranslations } from 'next-intl'
|
||||
|
||||
interface HeroHeaderProps {
|
||||
terminalVersion: string
|
||||
blogLabel: string
|
||||
aboutLabel: string
|
||||
}
|
||||
export function HeroHeader() {
|
||||
const locale = useLocale()
|
||||
const t = useTranslations('Home')
|
||||
const tNav = useTranslations('Navigation')
|
||||
|
||||
const terminalVersion = t('terminalVersion')
|
||||
const blogLabel = tNav('blog')
|
||||
const aboutLabel = tNav('about')
|
||||
|
||||
export function HeroHeader({ terminalVersion, blogLabel, aboutLabel }: HeroHeaderProps) {
|
||||
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false)
|
||||
const [isMobile, setIsMobile] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
const checkMobile = () => setIsMobile(window.innerWidth < 768)
|
||||
checkMobile()
|
||||
@@ -84,8 +87,9 @@ export function HeroHeader({ terminalVersion, blogLabel, aboutLabel }: HeroHeade
|
||||
>
|
||||
[{aboutLabel}]
|
||||
</Link>
|
||||
<div className="px-3 py-2">
|
||||
<div className="flex items-center gap-4 px-4 py-2">
|
||||
<ThemeToggle />
|
||||
<LanguageSwitcher />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -81,5 +81,5 @@ export function generateSlug(title: string): string {
|
||||
}
|
||||
|
||||
export function cn(...inputs: (string | undefined | null | false)[]): string {
|
||||
return inputs.filter(Boolean).join(" ")
|
||||
return inputs.filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
@@ -3,21 +3,21 @@
|
||||
"siteTitle": "Personal Blog",
|
||||
"siteDescription": "Thoughts on technology and development"
|
||||
},
|
||||
|
||||
"Navigation": {
|
||||
"home": "Home",
|
||||
"blog": "Blog",
|
||||
"tags": "Tags",
|
||||
"about": "About"
|
||||
},
|
||||
|
||||
"Breadcrumbs": {
|
||||
"home": "Home",
|
||||
"blog": "Blog",
|
||||
"tags": "Tags",
|
||||
"about": "About"
|
||||
"about": "About",
|
||||
"tech": "Technology",
|
||||
"design": "Design",
|
||||
"tutorial": "Tutorials"
|
||||
},
|
||||
|
||||
"Home": {
|
||||
"terminalVersion": "TERMINAL:// V2.0",
|
||||
"documentLevel": "DOCUMENT LEVEL-1 //",
|
||||
@@ -32,7 +32,6 @@
|
||||
"seePostsButton": "[SEE POSTS] >>",
|
||||
"seeAllTagsButton": "[SEE ALL TAGS] >>"
|
||||
},
|
||||
|
||||
"BlogListing": {
|
||||
"title": "Blog",
|
||||
"subtitle": "Latest articles and thoughts",
|
||||
@@ -48,7 +47,6 @@
|
||||
"prev": "< PREV",
|
||||
"next": "NEXT >"
|
||||
},
|
||||
|
||||
"BlogPost": {
|
||||
"readMore": "Read more",
|
||||
"readingTime": "{minutes} min read",
|
||||
@@ -58,7 +56,6 @@
|
||||
"relatedPosts": "Related Posts",
|
||||
"sharePost": "Share this post"
|
||||
},
|
||||
|
||||
"Tags": {
|
||||
"title": "Tags",
|
||||
"subtitle": "Browse by topic",
|
||||
@@ -67,7 +64,6 @@
|
||||
"relatedTags": "Related tags",
|
||||
"quickNav": "Quick navigation"
|
||||
},
|
||||
|
||||
"About": {
|
||||
"title": "About",
|
||||
"subtitle": "Learn more about me",
|
||||
@@ -119,13 +115,11 @@
|
||||
"techStackSelfHostingText": "Home lab, privacy-focused services, full control, Git server",
|
||||
"contactTitle": "> CONTACT"
|
||||
},
|
||||
|
||||
"NotFound": {
|
||||
"title": "Page Not Found",
|
||||
"description": "The page you're looking for doesn't exist",
|
||||
"goHome": "Go to homepage"
|
||||
},
|
||||
|
||||
"LanguageSwitcher": {
|
||||
"switchLanguage": "Switch language",
|
||||
"currentLanguage": "Current language"
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
"home": "Acasă",
|
||||
"blog": "Blog",
|
||||
"tags": "Etichete",
|
||||
"about": "Despre"
|
||||
"about": "Despre",
|
||||
"tech": "Tehnologie",
|
||||
"design": "Design",
|
||||
"tutorial": "Tutoriale"
|
||||
},
|
||||
"Home": {
|
||||
"terminalVersion": "TERMINAL:// V2.0",
|
||||
|
||||
Reference in New Issue
Block a user