diff --git a/src/components/HomepageHero/index.tsx b/src/components/HomepageHero/index.tsx index cecd4a1..5108f04 100644 --- a/src/components/HomepageHero/index.tsx +++ b/src/components/HomepageHero/index.tsx @@ -6,6 +6,7 @@ import { HoverEffect } from '@/components/ui/card-hover-effect' import { cn } from '@/lib/utils' import { PanelParticles } from '@/components/PanelParticles' +import { useLocale } from '@/hooks' export const StackItem = ({ className, @@ -25,32 +26,9 @@ export const StackItem = ({ } export default function HomepageHero() { - const featureList = [ - { - title: '先进的技术栈', - description: '高效的 React 框架和类型安全支持,使用 Next.js、TypeScript、TypeScript、和 Shadcn UI 打造现代化应用', - }, - { - title: 'Tailwind CSS & Iconify 图标集', - description: '原子化 CSS, 集成 Tailwind CSS 和 Iconify 图标集,轻松实现高效设计、响应式界面 UI', - }, - { - title: '暗黑模式', - description: '支持暗黑模式,提供更好的夜间使用体验', - }, - { - title: '代码规范', - description: '遵循最佳实践的代码规范,结合 ESLint 进行代码质量检查与一致性维护', - }, - { - title: '丰富组件 & 支持自由扩展', - description: '提供丰富的预置组件,并支持灵活的自定义扩展', - }, - { - title: '轻量化设计', - description: '采用轻量化设计,精简项目设置,专注于内容编写', - }, - ] + const { t } = useLocale() + + const featureList = t('featureList') const { resolvedTheme } = useTheme() diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts index 6d0a077..735048e 100644 --- a/src/hooks/useLocale.ts +++ b/src/hooks/useLocale.ts @@ -1,21 +1,25 @@ import { useCallback } from 'react' import { useRouter } from 'nextra/hooks' -import type { I18nLangKeys, LocaleKeys } from '@/i18n' +import type { AllLocales, I18nLangKeys, LocaleKeys, PathValue } from '@/i18n' import { getNestedValue, i18nConfig, interpolateString } from '@/i18n' +// 类型获取给定键的本地化值的类型 +type LocalizedValue = PathValue extends string + ? string + : PathValue export const useLocale = () => { const { locale, defaultLocale } = useRouter() const currentLocale = (locale || defaultLocale) as I18nLangKeys const t = useCallback( - (key: K, withData: Record = {}): string => { + (key: K, withData: Record = {}): LocalizedValue => { const template = getNestedValue(i18nConfig[currentLocale], key) if (typeof template === 'string') { - return interpolateString(template, withData) + return interpolateString(template, withData) as LocalizedValue } - return template || key + return template as LocalizedValue }, [currentLocale], ) diff --git a/src/i18n/en.ts b/src/i18n/en.ts index 658725e..30f31e0 100644 --- a/src/i18n/en.ts +++ b/src/i18n/en.ts @@ -6,4 +6,32 @@ export default { }, badgeTitle: 'Lightweight & Easy 🎉', + + featureList: [ + { + title: 'Advanced Tech Stack', + description: 'Leveraging efficient React frameworks and type-safe support with Next.js, TypeScript, and Shadcn UI to build modern applications.', + }, + { + title: 'Tailwind CSS & Iconify Icons', + description: 'Atomic CSS integrated with Tailwind CSS and Iconify icons, enabling efficient design and responsive UI.', + }, + { + title: 'Dark Mode', + description: 'Supports dark mode for an enhanced nighttime experience.', + }, + { + title: 'Code Standards', + description: 'Adheres to best practices with code standards and uses ESLint for quality checks and consistency.', + }, + { + title: 'Rich Components & Extensible Support', + description: 'Offers a range of built-in components and supports flexible custom extensions.', + }, + { + title: 'Lightweight Design', + description: 'Employs a lightweight design approach, streamlining project setup to focus on content creation.', + }, + ], + } diff --git a/src/i18n/index.ts b/src/i18n/index.ts index 4b4bed4..0d90c22 100644 --- a/src/i18n/index.ts +++ b/src/i18n/index.ts @@ -29,15 +29,28 @@ export type NestedKeyOf = { export type LocaleKeys = NestedKeyOf +type DeepObject = Record + +// 类型提取给定路径上值的类型 +export type PathValue = + P extends `${infer Key}.${infer Rest}` + ? Key extends keyof T + ? PathValue + : never + : P extends keyof T + ? T[P] + : never + // 获取嵌套值 -export function getNestedValue(obj: Record, path: string): any { - return path.split('.').reduce((acc, key) => acc && acc[key], obj) +export function getNestedValue(obj: T, path: K): PathValue { + return path.split('.').reduce((acc, key) => acc && acc[key], obj) as PathValue } + // 插入值表达式 export function interpolateString(template: string, context: Record): string { - return template.replace(/\{\{(\w+(\.\w+)*)\}\}/g, (_, path) => { - const value = getNestedValue(context, path) - return value !== undefined ? value : `{{${path}}}` + return template.replace(/\{\{\s*(\w+(\.\w+)*)\s*\}\}/g, (_, path) => { + const value = getNestedValue(context, path.trim()) + return value !== undefined ? value : `{{${path.trim()}}}` }) } diff --git a/src/i18n/zh.ts b/src/i18n/zh.ts index f709ff9..f72462d 100644 --- a/src/i18n/zh.ts +++ b/src/i18n/zh.ts @@ -6,4 +6,31 @@ export default { }, badgeTitle: '轻量级、开箱即用 🎉', + + featureList: [ + { + title: '先进的技术栈', + description: '高效的 React 框架和类型安全支持,使用 Next.js、TypeScript、TypeScript、和 Shadcn UI 打造现代化应用', + }, + { + title: 'Tailwind CSS & Iconify 图标集', + description: '原子化 CSS, 集成 Tailwind CSS 和 Iconify 图标集,轻松实现高效设计、响应式界面 UI', + }, + { + title: '暗黑模式', + description: '支持暗黑模式,提供更好的夜间使用体验', + }, + { + title: '代码规范', + description: '遵循最佳实践的代码规范,结合 ESLint 进行代码质量检查与一致性维护', + }, + { + title: '丰富组件 & 支持自由扩展', + description: '提供丰富的预置组件,并支持灵活的自定义扩展', + }, + { + title: '轻量化设计', + description: '采用轻量化设计,精简项目设置,专注于内容编写', + }, + ], }