feat: implement i18n routing and add localized footer component
This commit is contained in:
@@ -159,7 +159,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Footer": {
|
"Footer": {
|
||||||
|
"description": "Building secure, scalable, enterprise-grade systems. Specializing in banking & fintech infrastructure.",
|
||||||
|
"quickLinksTitle": "Quick Links",
|
||||||
|
"connectTitle": "Connect",
|
||||||
"backToTop": "Back to top",
|
"backToTop": "Back to top",
|
||||||
"copyright": "Yolando. Built with Next.js & crafted with purpose."
|
"copyright": "Yolando. All Rights Reserved."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,7 +159,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Footer": {
|
"Footer": {
|
||||||
|
"description": "Membangun sistem tingkat enterprise yang aman dan dapat diskalakan. Terspesialisasi dalam infrastruktur perbankan & fintech.",
|
||||||
|
"quickLinksTitle": "Tautan Cepat",
|
||||||
|
"connectTitle": "Terhubung",
|
||||||
"backToTop": "Kembali ke atas",
|
"backToTop": "Kembali ke atas",
|
||||||
"copyright": "Yolando. Dibangun dengan Next.js & dibuat dengan penuh tujuan."
|
"copyright": "Yolando. Semua Hak Cipta Dilindungi."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -147,9 +147,6 @@ export function ContactSection() {
|
|||||||
|
|
||||||
{/* Right — Form */}
|
{/* Right — Form */}
|
||||||
<div className="lg:col-span-3 relative p-6 md:p-8 rounded-2xl bg-card border border-border/50 shadow-lg">
|
<div className="lg:col-span-3 relative p-6 md:p-8 rounded-2xl bg-card border border-border/50 shadow-lg">
|
||||||
{/* Subtle top accent */}
|
|
||||||
<div className="absolute top-0 inset-x-0 h-0.5 bg-gradient-to-r from-accent to-purple-500 rounded-t-2xl" />
|
|
||||||
|
|
||||||
{/* Success overlay */}
|
{/* Success overlay */}
|
||||||
{formState === "success" && (
|
{formState === "success" && (
|
||||||
<div className="absolute inset-0 flex items-center justify-center bg-card/95 rounded-2xl z-10">
|
<div className="absolute inset-0 flex items-center justify-center bg-card/95 rounded-2xl z-10">
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import {createNavigation} from 'next-intl/navigation';
|
|||||||
export const routing = defineRouting({
|
export const routing = defineRouting({
|
||||||
locales: ['id', 'en'],
|
locales: ['id', 'en'],
|
||||||
defaultLocale: 'id',
|
defaultLocale: 'id',
|
||||||
localePrefix: 'as-needed' // Don't show /id for the default locale
|
localePrefix: 'as-needed', // Don't show /id for the default locale
|
||||||
|
localeDetection: false // Force id on first visit regardless of browser lang
|
||||||
});
|
});
|
||||||
|
|
||||||
export const {Link, redirect, usePathname, useRouter, getPathname} = createNavigation(routing);
|
export const {Link, redirect, usePathname, useRouter, getPathname} = createNavigation(routing);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const quickLinks = [
|
|||||||
|
|
||||||
export function Footer() {
|
export function Footer() {
|
||||||
const t = useTranslations("Footer");
|
const t = useTranslations("Footer");
|
||||||
|
const tNav = useTranslations("Navigation");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<footer className="relative border-t border-border/50 bg-card/50">
|
<footer className="relative border-t border-border/50 bg-card/50">
|
||||||
@@ -29,8 +30,7 @@ export function Footer() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground leading-relaxed mb-4 max-w-xs">
|
<p className="text-sm text-muted-foreground leading-relaxed mb-4 max-w-xs">
|
||||||
Building secure, scalable, enterprise-grade systems.
|
{t("description")}
|
||||||
Specializing in banking & fintech infrastructure.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-1.5 text-xs text-muted-foreground/60">
|
<div className="flex items-center gap-1.5 text-xs text-muted-foreground/60">
|
||||||
<MapPin size={12} />
|
<MapPin size={12} />
|
||||||
@@ -41,7 +41,7 @@ export function Footer() {
|
|||||||
{/* Quick Links */}
|
{/* Quick Links */}
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-sm font-bold mb-4 uppercase tracking-wider text-muted-foreground">
|
<h4 className="text-sm font-bold mb-4 uppercase tracking-wider text-muted-foreground">
|
||||||
Quick Links
|
{t("quickLinksTitle", { fallback: "Quick Links" })}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
{quickLinks.map((link) => (
|
{quickLinks.map((link) => (
|
||||||
@@ -50,7 +50,7 @@ export function Footer() {
|
|||||||
href={link.href}
|
href={link.href}
|
||||||
className="block text-sm text-muted-foreground hover:text-accent transition-colors"
|
className="block text-sm text-muted-foreground hover:text-accent transition-colors"
|
||||||
>
|
>
|
||||||
{link.label}
|
{tNav(link.label?.toLowerCase() === "tech stack" ? "techStack" : link.label.toLowerCase() as any)}
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@@ -60,20 +60,11 @@ export function Footer() {
|
|||||||
<div className="flex flex-col items-start md:items-end gap-6">
|
<div className="flex flex-col items-start md:items-end gap-6">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-sm font-bold mb-4 uppercase tracking-wider text-muted-foreground md:text-right">
|
<h4 className="text-sm font-bold mb-4 uppercase tracking-wider text-muted-foreground md:text-right">
|
||||||
Connect
|
{t("connectTitle", { fallback: "Connect" })}
|
||||||
</h4>
|
</h4>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<a
|
<a
|
||||||
href="https://github.com/yolandoando"
|
href="https://www.linkedin.com/in/yolando-asri-e-g-manullang/"
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="p-2.5 rounded-xl bg-muted/50 border border-border/50 hover:bg-accent hover:text-accent-foreground hover:border-accent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-accent/20"
|
|
||||||
aria-label="GitHub"
|
|
||||||
>
|
|
||||||
<GitFork size={18} />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://linkedin.com/in/yolandoando"
|
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="p-2.5 rounded-xl bg-muted/50 border border-border/50 hover:bg-accent hover:text-accent-foreground hover:border-accent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-accent/20"
|
className="p-2.5 rounded-xl bg-muted/50 border border-border/50 hover:bg-accent hover:text-accent-foreground hover:border-accent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-accent/20"
|
||||||
@@ -82,7 +73,7 @@ export function Footer() {
|
|||||||
<Link2 size={18} />
|
<Link2 size={18} />
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="mailto:yolando@pm.me"
|
href="mailto:yolandomanullang@gmail.com"
|
||||||
className="p-2.5 rounded-xl bg-muted/50 border border-border/50 hover:bg-accent hover:text-accent-foreground hover:border-accent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-accent/20"
|
className="p-2.5 rounded-xl bg-muted/50 border border-border/50 hover:bg-accent hover:text-accent-foreground hover:border-accent transition-all duration-300 hover:scale-105 hover:shadow-lg hover:shadow-accent/20"
|
||||||
aria-label="Email"
|
aria-label="Email"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user