feat(i18n): implement internationalization support for en and zh
Add i18n infrastructure with translation files and utility functions Update components to use translations and language switching Create localized pages for en and zh languages Add language detection and path localization utilities
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import ThemeToggle from "./ui/theme-toggle";
|
||||
import LanguageSwitcher from "./LanguageSwitcher"; // Added import for LanguageSwitcher
|
||||
import LanguageSwitcher from "./LanguageSwitcher";
|
||||
import { useTranslations, getLocalizedPath, type Lang } from "@/i18n/utils";
|
||||
import { personalInfo } from "@/lib/data";
|
||||
import { useState } from "react";
|
||||
import { Menu, X } from "lucide-react";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
|
||||
export default function GlassHeader() {
|
||||
interface GlassHeaderProps {
|
||||
lang: Lang;
|
||||
}
|
||||
|
||||
export default function GlassHeader({ lang }: GlassHeaderProps) {
|
||||
const t = useTranslations(lang);
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
|
||||
const toggleMenu = () => setIsMenuOpen(!isMenuOpen);
|
||||
@@ -15,7 +21,7 @@ export default function GlassHeader() {
|
||||
<div className="container max-w-4xl mx-auto p-4 flex justify-between items-center">
|
||||
<motion.a
|
||||
className="flex items-center text-lg font-medium"
|
||||
href="/"
|
||||
href={getLocalizedPath('/', lang)}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
whileTap={{ scale: 0.95 }}
|
||||
>
|
||||
@@ -24,23 +30,25 @@ export default function GlassHeader() {
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<nav className="hidden md:flex items-center space-x-6 text-sm font-medium">
|
||||
{["experience", "skills", "projects", "awards", "education"].map(
|
||||
{[
|
||||
{ key: 'nav.experience', icon: '💼 ', sectionId: 'experience' },
|
||||
{ key: 'nav.skills', icon: '🛠️ ', sectionId: 'skills' },
|
||||
{ key: 'nav.projects', icon: '🚀 ', sectionId: 'projects' },
|
||||
{ key: 'nav.awards', icon: '🏆 ', sectionId: 'awards' },
|
||||
{ key: 'nav.education', icon: '🎓 ', sectionId: 'education' },
|
||||
].map(
|
||||
(item, index) => (
|
||||
<motion.a
|
||||
key={item}
|
||||
href={`#${item}`}
|
||||
key={item.key} // Changed from item to item.key
|
||||
href={`#${item.sectionId}`}
|
||||
className="transition-colors hover:text-foreground/80 text-foreground/60"
|
||||
initial={{ opacity: 0, y: -10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.2, delay: index * 0.1 }}
|
||||
whileHover={{ y: -2 }}
|
||||
>
|
||||
{item === "experience" && "💼 "}
|
||||
{item === "skills" && "🛠️ "}
|
||||
{item === "projects" && "🚀 "}
|
||||
{item === "awards" && "🏆 "}
|
||||
{item === "education" && "🎓 "}
|
||||
{item.charAt(0).toUpperCase() + item.slice(1)}
|
||||
{item.icon}
|
||||
{t(item.key as any) /* Type assertion needed if UiKeys is strict */}
|
||||
</motion.a>
|
||||
)
|
||||
)}
|
||||
@@ -48,7 +56,7 @@ export default function GlassHeader() {
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
{/* Language Switcher added here */}
|
||||
<LanguageSwitcher />
|
||||
<LanguageSwitcher lang={lang} />
|
||||
<ThemeToggle />
|
||||
|
||||
{/* Mobile Menu Button */}
|
||||
@@ -74,23 +82,25 @@ export default function GlassHeader() {
|
||||
transition={{ duration: 0.3 }}
|
||||
>
|
||||
<nav className="flex flex-col space-y-4 text-sm font-medium">
|
||||
{["experience", "skills", "projects", "awards", "education"].map(
|
||||
{[
|
||||
{ key: 'nav.experience', icon: '💼 ', sectionId: 'experience' },
|
||||
{ key: 'nav.skills', icon: '🛠️ ', sectionId: 'skills' },
|
||||
{ key: 'nav.projects', icon: '🚀 ', sectionId: 'projects' },
|
||||
{ key: 'nav.awards', icon: '🏆 ', sectionId: 'awards' },
|
||||
{ key: 'nav.education', icon: '🎓 ', sectionId: 'education' },
|
||||
].map(
|
||||
(item, index) => (
|
||||
<motion.a
|
||||
key={item}
|
||||
href={`#${item}`}
|
||||
key={item.key} // Changed from item to item.key
|
||||
href={`#${item.sectionId}`}
|
||||
className="transition-colors hover:text-foreground/80 text-foreground/60 py-2"
|
||||
onClick={toggleMenu}
|
||||
initial={{ opacity: 0, x: -20 }}
|
||||
animate={{ opacity: 1, x: 0 }}
|
||||
transition={{ duration: 0.2, delay: index * 0.1 }}
|
||||
>
|
||||
{item === "experience" && "💼 "}
|
||||
{item === "skills" && "🛠️ "}
|
||||
{item === "projects" && "🚀 "}
|
||||
{item === "awards" && "🏆 "}
|
||||
{item === "education" && "🎓 "}
|
||||
{item.charAt(0).toUpperCase() + item.slice(1)}
|
||||
{item.icon}
|
||||
{t(item.key as any) /* Type assertion needed if UiKeys is strict */}
|
||||
</motion.a>
|
||||
)
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user