From a8ab7e68110443c80de65f0f39f5c5ae73b261e9 Mon Sep 17 00:00:00 2001 From: zguiyang Date: Sat, 14 Mar 2026 12:05:23 +0800 Subject: [PATCH] refactor(about): modernize and unify `About` pages with improved design and translations - Replaced `.mdx` files for `about` pages with `.astro` format to streamline layout and enhance flexibility. - Integrated `GlassHeader`, `HighlightBox`, and other reusable components for consistency. - Enhanced design with dynamic backgrounds, gradients, and interactive hover effects. - Updated i18n translations to support structured nested keys for improved localization and scalability. - Refined contact and skills sections with responsive layouts and clearer organization. --- src/i18n/translations.ts | 86 ++++++++++++++++++-- src/i18n/utils.ts | 52 +++++++++--- src/pages/about.astro | 169 +++++++++++++++++++++++++++++++++++++++ src/pages/about.mdx | 71 ---------------- src/pages/zh/about.astro | 169 +++++++++++++++++++++++++++++++++++++++ src/pages/zh/about.mdx | 68 ---------------- 6 files changed, 460 insertions(+), 155 deletions(-) create mode 100644 src/pages/about.astro delete mode 100644 src/pages/about.mdx create mode 100644 src/pages/zh/about.astro delete mode 100644 src/pages/zh/about.mdx diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts index 185f7b3..e396a84 100644 --- a/src/i18n/translations.ts +++ b/src/i18n/translations.ts @@ -78,9 +78,46 @@ export const translations = { }, about: { title: 'About Me', - sectionTitle: 'About Me', - learnMore: 'Learn More About Me', - toolbox: 'My Toolbox', + description: 'Learn more about my background, skills, and experiences', + intro: { + title: 'Introduction', + content: "I'm a TypeScript Full Stack Engineer who loves development, technology, and exploring new possibilities. I enjoy bringing digital projects to life. 🚀", + belief: "I believe this is where ideas become reality. I'm exploring the freelance journey, striving to become a digital nomad.", + }, + me: { + title: 'About me 🧠', + content: "I started my programming journey in 2016 when I accidentally encountered programming. This opportunity became the catalyst for my coding adventure, and I fell in love with programming during my subsequent self-learning journey. \n\nI enjoy creating websites and applications with code and sharing them with users. The sense of achievement I get from this process makes me increasingly fascinated. My dream is to become a lifelong coder.", + }, + skills: { + title: 'My Skills 💪', + description: "Below are the technology stacks I'm currently familiar with or proficient in, as well as those I'm learning or planning to learn.", + mastered: { + title: "Skills I've Mastered", + items: ['HTML, CSS, JavaScript', 'Frontend Frameworks: Vue.js, React.js, Node.js, uniApp, WeChat Mini Program', 'TypeScript', 'Databases: MySQL, MongoDB', 'DevOps: Linux, Git', 'Others: Markdown, Docker, Kubernetes, Nginx, Apache, etc.'], + }, + learning: { + title: "Skills I'm Learning/Planning to Learn", + items: ['Programming Languages: Python, Java, Go', 'Mobile Development: Flutter, Dart', 'iOS Development: Swift, SwiftUI'], + }, + }, + interests: { + title: 'My Interests 🌈', + items: [ + { title: 'Reading', content: 'I enjoy reading various books, especially technical ones.' }, + { title: 'Travel', content: 'I like visiting different places, particularly on road trips.' }, + { title: 'Food', content: 'I enjoy various cuisines, especially hot pot.' }, + { title: 'Mobile Games', content: 'I like playing League of Legends, Honor of Kings, PUBG Mobile, and other mobile games.' }, + ], + }, + contact: { + title: 'Contact Me 📫', + warning: 'Since everyone\'s time is valuable, please add a note when contacting me, such as: collaboration, consultation, project requirements, etc. I may not reply to or might ignore messages without notes. Thank you for your cooperation!', + methods: { + email: 'Email: zhaoguiyang18@gmail.com', + qq: 'QQ: 2770723534', + wechat: 'WeChat: JoyCodeing', + }, + }, }, home: { hero: { @@ -218,9 +255,46 @@ export const translations = { }, about: { title: '关于我', - sectionTitle: '关于我', - learnMore: '了解更多', - toolbox: '我的工具箱', + description: '了解更多关于我的背景、技能和经验', + intro: { + title: '简介', + content: '我是Joy Zhao, 一名Ts全栈工程师,也是本站的站长。\n\n热爱生活、阅读以及编程,寻找远程工作的机会,探索自由职业的可能性。\n喜欢自驾,去追寻那些美丽的风景,尝试新的事物。', + belief: '我相信这里是想法变为现实的地方。我正在探索自由职业者之路,努力成为数字游民中的一员。', + }, + me: { + title: '自我介绍 🧠', + content: '在2016年一次偶然的机会中接触到了编程,以此为契机,开始了我的编程之旅,并在后续的自学之旅中爱上了编程,我喜欢用代码编写出一个个的网页、应用,分享给用户使用,这其中获得的成就感让我愈发着迷。梦想是成为一名终身编码者。', + }, + skills: { + title: '我的技能 💪', + description: '以下展示了我目前熟悉或精通的技术栈,以及正在/准备学习的技术栈。', + mastered: { + title: '已掌握的技能', + items: ['HTML、CSS、JavaScript', 'Vue.js、React.js、Node.js、uniApp、微信小程序等前端框架', 'TypeScript', 'MySQL、MongoDB', 'Linux、Git', '其他:Markdown、Docker、Kubernetes、Nginx、Apache等技术'], + }, + learning: { + title: '正在/准备学习的技能', + items: ['Python、Java、Go', 'Flutter、Dart', 'Swift、SwiftUI'], + }, + }, + interests: { + title: '兴趣爱好 🌈', + items: [ + { title: '阅读', content: '喜欢阅读各种书籍,尤其是技术类书籍。' }, + { title: '旅游', content: '喜欢去不同的地方看看,尤其是自驾游。' }, + { title: '美食', content: '喜欢吃各种美食,尤其是火锅。' }, + { title: '手游', content: '喜欢玩英雄联盟、王者荣耀、绝地求生等手游。' }, + ], + }, + contact: { + title: '联系我 📫', + warning: '由于大家的时间都很宝贵,所以请在联系我时添加备注,如:合作、咨询、项目需求等,不予备注的我可能不会回复或直接忽略,谢谢合作!', + methods: { + email: '邮箱:zhaoguiyang18@gmail.com', + qq: 'QQ: 2770723534', + wechat: '微信:JoyCodeing', + }, + }, }, home: { hero: { diff --git a/src/i18n/utils.ts b/src/i18n/utils.ts index 043fc3d..5388f9f 100644 --- a/src/i18n/utils.ts +++ b/src/i18n/utils.ts @@ -1,4 +1,4 @@ -import { defaultLang, languages, flatTranslations } from './translations'; +import { defaultLang, languages, flatTranslations, translations } from './translations'; import type { Lang } from '@/types/i18n'; export type TranslationKey = string; @@ -6,27 +6,59 @@ export type TranslationKey = string; export function useTranslations(lang: Lang | undefined) { const currentLang = lang || defaultLang; - return function t(key: TranslationKey, ...args: any[]): string { - let translation = flatTranslations[currentLang][key]; + function t(key: TranslationKey, ...args: any[]): any { + let translation: any = flatTranslations[currentLang][key]; - if (!translation && currentLang !== defaultLang) { + // Fallback to raw translations for objects/arrays + if (translation === undefined) { + const keys = key.split('.'); + let current: any = translations[currentLang as keyof typeof translations]; + for (const k of keys) { + if (current && typeof current === 'object' && k in current) { + current = current[k]; + } else { + current = undefined; + break; + } + } + translation = current; + } + + if (translation === undefined && currentLang !== defaultLang) { translation = flatTranslations[defaultLang][key]; + if (translation === undefined) { + const keys = key.split('.'); + let current: any = translations[defaultLang as keyof typeof translations]; + for (const k of keys) { + if (current && typeof current === 'object' && k in current) { + current = current[k]; + } else { + current = undefined; + break; + } + } + translation = current; + } } - if (!translation) { + if (translation === undefined) { console.warn(`Translation key not found: ${key}`); return key; } - // Replace placeholders with arguments - if (args.length > 0) { + // Replace placeholders with arguments if it's a string + if (typeof translation === 'string' && args.length > 0) { + let result = translation; args.forEach((arg, index) => { - translation = translation.replace(`{${index}}`, String(arg)); + result = result.replace(`{${index}}`, String(arg)); }); + return result; } return translation; - }; + } + + return t; } /** @@ -66,4 +98,4 @@ export function getLocalizedPath(path: string, lang: Lang | undefined): string { // Combine with base path and clean up any double slashes const fullPath = `${basePath}${newPath}`; return fullPath.replace(/\/\/+/g, '/'); -} \ No newline at end of file +} diff --git a/src/pages/about.astro b/src/pages/about.astro new file mode 100644 index 0000000..d043991 --- /dev/null +++ b/src/pages/about.astro @@ -0,0 +1,169 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import GlassHeader from "@/components/GlassHeader"; +import Footer from "@/components/Footer"; +import Container from "@/components/ui/Container.astro"; +import HighlightBox from "@/components/markdown/HighlightBox.astro"; +import { useTranslations } from "@/i18n/utils"; +import type { Lang } from "@/types/i18n"; +import { defaultLang } from "@/i18n/ui"; +import { Sparkles, Heart, Zap, Mail, MessageSquare } from "lucide-react"; + +const lang = (Astro.currentLocale as Lang) || defaultLang; +const t = useTranslations(lang); +const pageTitle = t("about.title"); +--- + + + + +
+ +
+
+
+ + +
+ +
+
+
+
+
+ Joy Zhao +
+
+ +
+

+ + {t('about.title')} + +

+

+ {t('about.description')} +

+
+
+ +
+ + +
+

{t('about.intro.content')}

+
+ {t('about.intro.belief')} +
+
+
+ + +
+

+ + {t('about.me.title')} +

+
+

+ {t('about.me.content')} +

+
+
+ + +
+
+

+ + {t('about.skills.mastered.title')} +

+
    + {(t('about.skills.mastered.items') as unknown as string[]).map((item: string) => ( +
  • + + {item} +
  • + ))} +
+
+ +
+

+ + {t('about.skills.learning.title')} +

+
    + {(t('about.skills.learning.items') as unknown as string[]).map((item: string) => ( +
  • + + {item} +
  • + ))} +
+
+
+ + +
+

+ {t('about.interests.title')} +

+
+ {(t('about.interests.items') as unknown as any[]).map((item) => ( +
+

{item.title}

+

{item.content}

+
+ ))} +
+
+ + +
+
+ +
+ +
+

+ + {t('about.contact.title')} +

+ + + {t('about.contact.warning')} + + +
+
+ + Email + {(t('about.contact.methods.email') as string).split(':')[1] || (t('about.contact.methods.email') as string).split(': ')[1]} +
+
+ QQ + QQ + {(t('about.contact.methods.qq') as string).split(':')[1] || (t('about.contact.methods.qq') as string).split(': ')[1]} +
+
+ + WeChat + {(t('about.contact.methods.wechat') as string).split(':')[1] || (t('about.contact.methods.wechat') as string).split(': ')[1]} +
+
+
+
+
+
+
+
+
+ +