diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index eb07678..8470efc 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,4 +1,5 @@ -import { useTranslations, type Lang } from "@/i18n/utils"; +import { useTranslations } from "@/i18n/utils"; +import type { Lang } from "@/types/i18n"; import { personalInfo } from "@/lib/data"; import { motion } from "framer-motion"; import { useState, useEffect } from "react"; @@ -7,11 +8,9 @@ import Container from "./ui/Container"; import { type FooterProps } from "@/types"; export default function Footer({ lang: propLang }: FooterProps) { - // 优先使用props传入的语言,如果没有则尝试从HTML lang属性获取 const [lang, setLang] = useState(propLang || defaultLang); useEffect(() => { - // 在客户端运行时,从HTML lang属性获取当前语言 const htmlLang = document.documentElement.lang as Lang; if (htmlLang && (!propLang || htmlLang !== lang)) { setLang(htmlLang); diff --git a/src/components/GlassHeader.tsx b/src/components/GlassHeader.tsx index c6d3ccd..f7bbdae 100644 --- a/src/components/GlassHeader.tsx +++ b/src/components/GlassHeader.tsx @@ -2,21 +2,17 @@ import { personalInfo } from "@/lib/data"; import LanguageSwitcher from "./LanguageSwitcher"; import ThemeToggle from "./ui/theme-toggle"; import Container from "./ui/Container"; -import { useTranslations, getLocalizedPath, type Lang } from "@/i18n/utils"; +import { useTranslations, getLocalizedPath } from "@/i18n/utils"; +import type { Lang } from "@/types/i18n"; import { useState, useEffect } from "react"; -import { motion, AnimatePresence } from "framer-motion"; import { Menu, X } from "lucide-react"; import { defaultLang } from "@/i18n/ui"; import { type GlassHeaderProps } from "@/types"; -// 从window.document.documentElement.lang获取当前语言 - export default function GlassHeader({ lang: propLang }: GlassHeaderProps) { - // 优先使用props传入的语言,如果没有则尝试从HTML lang属性获取 const [lang, setLang] = useState(propLang || defaultLang); useEffect(() => { - // 在客户端运行时,从HTML lang属性获取当前语言 const htmlLang = document.documentElement.lang as Lang; if (htmlLang && (!propLang || htmlLang !== lang)) { setLang(htmlLang); diff --git a/src/components/LanguageSwitcher.tsx b/src/components/LanguageSwitcher.tsx index 38a50b0..b535435 100644 --- a/src/components/LanguageSwitcher.tsx +++ b/src/components/LanguageSwitcher.tsx @@ -1,23 +1,21 @@ import { useState, useEffect } from "react"; -import { getLocalizedPath, type Lang } from "@/i18n/utils"; +import { getLocalizedPath } from "@/i18n/utils"; +import type { Lang } from "@/types/i18n"; import { languages as i18nLanguages, defaultLang } from "@/i18n/ui"; -import { Languages, Check, ChevronDown } from "lucide-react"; +import { Check, ChevronDown } from "lucide-react"; import { motion, AnimatePresence } from "framer-motion"; import { type LanguageSwitcherProps } from "@/types"; const availableLanguages = Object.entries(i18nLanguages).map(([code, name]) => ({ code: code as Lang, name, - // 语言图标映射 icon: code === 'en' ? '🇬🇧' : code === 'zh' ? '🇨🇳' : '🌐' })); export default function LanguageSwitcher({ lang: propLang }: LanguageSwitcherProps) { const [isOpen, setIsOpen] = useState(false); - // 获取当前语言,优先使用props传入的语言 const [currentLang, setCurrentLang] = useState(propLang || defaultLang); - // 在客户端运行时,从HTML lang属性获取当前语言 useEffect(() => { if (typeof document !== 'undefined') { const htmlLang = document.documentElement.lang as Lang; @@ -50,39 +48,28 @@ export default function LanguageSwitcher({ lang: propLang }: LanguageSwitcherPro const currentPathParts = currentPathname.split('/').filter(p => p); let basePath = ''; - // Check if the first part of the path is a known language code if (currentPathParts.length > 0 && Object.keys(i18nLanguages).includes(currentPathParts[0])) { - // If the first part is a language code, remove it to get the base path basePath = '/' + currentPathParts.slice(1).join('/'); } else { - // If no language code in path, use the current path as base basePath = currentPathname; } - // Ensure basePath always starts with a slash, or is just a slash for the root if (!basePath.startsWith('/')) { basePath = '/' + basePath; } - // Fix for empty paths if (basePath === '//') basePath = '/'; if (basePath === '') basePath = '/'; let newPath; - // If the target language is the default language and prefixDefaultLocale is false (as per our astro.config.mjs) - // then no language prefix is needed. if (languageOpt.code === defaultLang) { newPath = basePath; } else { - // For non-default languages, prefix with the language code. newPath = `/${languageOpt.code}${basePath}`; } - // Clean up double slashes, just in case newPath = newPath.replace(/\/\/+/g, '/'); - // Handle case where basePath might be empty resulting in just /zh or /en if (newPath === '') newPath = '/'; - // Prevent unnecessary redirects to the same page if (newPath !== currentPathname) { window.location.href = newPath; } @@ -120,7 +107,7 @@ export default function LanguageSwitcher({ lang: propLang }: LanguageSwitcherPro role="menuitem" > - {lang.icon} {/* Display icon */} + {lang.icon} {lang.name} {selectedLanguage.code === lang.code && } diff --git a/src/components/SkillsMarquee.tsx b/src/components/SkillsMarquee.tsx index a723f26..b3d53b7 100644 --- a/src/components/SkillsMarquee.tsx +++ b/src/components/SkillsMarquee.tsx @@ -2,10 +2,6 @@ import { motion, type Variants } from "framer-motion"; import { useTranslations } from "@/i18n/utils"; import { type SkillItem } from "@/types"; -/** - * All skills data with corresponding skillicons names - * Using skillicons.dev for consistent icon display - */ const allSkills: SkillItem[] = [ // Programming Languages { name: "TypeScript", icon: "typescript" }, diff --git a/src/components/ui/Container.tsx b/src/components/ui/Container.tsx index 3973389..6e8f4f0 100644 --- a/src/components/ui/Container.tsx +++ b/src/components/ui/Container.tsx @@ -6,11 +6,6 @@ interface ContainerProps { className?: string; } -/** - * Container component for consistent content width across the site - * @param children - The content to be wrapped - * @param className - Additional classes to apply - */ export default function Container({ children, className diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index 3ed9851..b71dff8 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -1,25 +1,9 @@ -/** - * Translations module - * Contains all translation data for the application - */ - -/** - * Available languages in the application - */ export const languages = { en: 'English', zh: '简体中文', } as const; -/** - * Default language for the application - */ export const defaultLang = 'en'; - -/** - * Structured translations data - * Organized by language and feature area - */ export const translations = { en: { nav: { diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index 2d03f0d..043fc3d 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -1,44 +1,18 @@ -/** - * Internationalization utilities module - * Contains helper functions for i18n functionality - */ import { defaultLang, languages, flatTranslations } from './translations'; import type { Lang } from '@/types/i18n'; -/** - * Translation key type - * Represents a dot-notation path to a translation string - */ export type TranslationKey = string; -/** - * Get translation function - * Returns a function that can be used to get translations for a specific language - * - * @param lang - The language to get translations for - * @returns A translation function - */ export function useTranslations(lang: Lang | undefined) { const currentLang = lang || defaultLang; - /** - * Translation function - * Gets a translation string for the specified key and replaces placeholders - * - * @param key - The translation key (dot notation) - * @param args - Optional arguments to replace placeholders in the translation - * @returns The translated string - */ return function t(key: TranslationKey, ...args: any[]): string { - // Get translation from flattened translations for better performance let translation = flatTranslations[currentLang][key]; - // Fallback to default language if translation not found if (!translation && currentLang !== defaultLang) { translation = flatTranslations[defaultLang][key]; } - // Fallback to key if translation not found in any language if (!translation) { console.warn(`Translation key not found: ${key}`); return key; diff --git a/src/lib/data.ts b/src/lib/data.ts index f0b1274..03d99a0 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -1,23 +1,7 @@ -/** - * Data module (Legacy) - * This file is kept for backward compatibility - * All data has been moved to src/lib/data/ directory - */ - -// Re-export all data from the new modules export { personalInfo } from './data/personal-info'; export { projects } from './data/projects'; export { services } from './data/services'; -// For TypeScript type checking -import { personalInfo } from './data/personal-info'; -import { projects } from './data/projects'; -import { services } from './data/services'; - -// Type exports are now handled in src/types/index.ts -// This file is now just a re-export wrapper -// The actual data is in the respective files in src/lib/data/ directory - // export const projects = { // en: [{ // id: "taskify", diff --git a/src/lib/data/index.ts b/src/lib/data/index.ts index 77d5659..30db750 100644 --- a/src/lib/data/index.ts +++ b/src/lib/data/index.ts @@ -1,9 +1,3 @@ -/** - * Data index module - * Re-exports all data modules to maintain backward compatibility - */ - -// Re-export all data modules export { personalInfo } from './personal-info'; export { projects } from './projects'; export { services } from './services'; \ No newline at end of file diff --git a/src/lib/data/personal-info.ts b/src/lib/data/personal-info.ts index c1207e9..6a08157 100644 --- a/src/lib/data/personal-info.ts +++ b/src/lib/data/personal-info.ts @@ -1,13 +1,4 @@ -/** - * Personal information data module - * Contains all personal information used throughout the site - */ import type { PersonalInfo } from '@/types'; - -/** - * Personal information data - * This data is used in various components like Header, Footer, and About sections - */ export const personalInfo: PersonalInfo = { name: "Joy Zhao", location: "China", diff --git a/src/lib/data/projects.ts b/src/lib/data/projects.ts index 4012f11..6ab609d 100644 --- a/src/lib/data/projects.ts +++ b/src/lib/data/projects.ts @@ -1,13 +1,4 @@ -/** - * Projects data module - * Contains all project information displayed in the projects page - */ import type { Project } from '@/types'; - -/** - * Projects data with localization support - * Each project contains information like id, tag, title, description, tech stack, etc. - */ export const projects = { en: [ { diff --git a/src/lib/data/services.ts b/src/lib/data/services.ts index e092681..7961dfe 100644 --- a/src/lib/data/services.ts +++ b/src/lib/data/services.ts @@ -1,13 +1,4 @@ -/** - * Services data module - * Contains all service information displayed in the services section - */ import type { Service } from '@/types'; - -/** - * Services data with localization support - * Each service contains information like title, icon, items, and color - */ export const services = { en: [ { diff --git a/src/types/components.ts b/src/types/components.ts index cd559a3..affd4b2 100644 --- a/src/types/components.ts +++ b/src/types/components.ts @@ -10,7 +10,7 @@ import type { Lang } from './i18n'; export interface SkillItem { name: string; icon: string; - color: string; + color?: string; } /** diff --git a/src/types/data.ts b/src/types/data.ts index e3f930a..034b8b0 100644 --- a/src/types/data.ts +++ b/src/types/data.ts @@ -1,19 +1,9 @@ -/** - * Data types module - * Contains type definitions for all data structures used in the application - */ import type { Lang } from './i18n.ts'; -/** - * Multi-language text type - */ export type LocalizedText = { [K in Lang]: string; }; -/** - * Personal information interface - */ export interface PersonalInfo { name: string; location: string; @@ -45,18 +35,12 @@ export interface PersonalInfo { }; } -/** - * Project image interface - */ export interface ProjectImage { bg: string; hover: string; text: string; } -/** - * Project interface - */ export interface Project { id: string; tag: string; @@ -69,17 +53,11 @@ export interface Project { link: string; } -/** - * Service icon interface - */ export interface ServiceIcon { svg: string; gradient: string; } -/** - * Service interface - */ export interface Service { title: string; icon: ServiceIcon; diff --git a/src/types/i18n.ts b/src/types/i18n.ts index 0ab22b5..2348ca6 100644 --- a/src/types/i18n.ts +++ b/src/types/i18n.ts @@ -1,36 +1,17 @@ -/** - * Internationalization types module - * Contains type definitions for i18n functionality - */ import { languages } from '@/i18n/translations'; -/** - * Language type definition - */ export type Lang = keyof typeof languages; -/** - * UI translation keys type - */ export type UiKeys = string; -/** - * Language switcher component props - */ export interface LanguageSwitcherProps { lang: Lang; } -/** - * Glass header component props - */ export interface GlassHeaderProps { lang: Lang; } -/** - * Footer component props - */ export interface FooterProps { lang?: Lang; } \ No newline at end of file