From e64a874499110a29d7fd022d720d7d48584fb6f0 Mon Sep 17 00:00:00 2001 From: yuzhiran-dev Date: Mon, 25 May 2026 09:22:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=AF=BC=E8=88=AA=20i18n=20=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=20+=20=E6=A8=A1=E5=9E=8B/=E6=8F=90=E7=A4=BA=E8=AF=8D?= =?UTF-8?q?=E9=A1=B5=20useT()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Header 导航 skills/models/articles 改为 t.nav.*(英文正常显示) - 模型百科页全部文字使用 useT()(表格标题、标签等) - 提示词库页标题使用 useT() - models 翻译键补全 contextWindow/maxOutput --- frontend/src/app/models/page.tsx | 73 +++++++---------------- frontend/src/app/prompts/page.tsx | 39 ++++-------- frontend/src/components/layout/header.tsx | 6 +- frontend/src/i18n/locales/en.ts | 4 +- frontend/src/i18n/locales/zh.ts | 4 +- 5 files changed, 39 insertions(+), 87 deletions(-) diff --git a/frontend/src/app/models/page.tsx b/frontend/src/app/models/page.tsx index c163276..608172e 100644 --- a/frontend/src/app/models/page.tsx +++ b/frontend/src/app/models/page.tsx @@ -3,45 +3,24 @@ import { useEffect, useState } from 'react'; import { Skeleton } from '@/components/ui/skeleton'; import { API_BASE } from '@/lib/config'; +import { useT } from '@/i18n'; -interface AiModel { - id: number; - name: string; - provider: string; - description: string | null; - capabilities: string | null; - contextWindow: number | null; - maxTokens: number | null; - pricing: string | null; - isFree: boolean; - isFeatured: boolean; - icon: string | null; -} +interface AiModel { id: number; name: string; provider: string; description: string | null; capabilities: string | null; contextWindow: number | null; maxTokens: number | null; pricing: string | null; isFree: boolean; isFeatured: boolean; icon: string | null } export default function ModelsPage() { + const t = useT(); const [models, setModels] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { - fetch(`${API_BASE}/models`) - .then(r => r.json()) - .then(setModels) - .catch(() => {}) - .finally(() => setLoading(false)); + fetch(`${API_BASE}/models`).then(r => r.json()).then(setModels).catch(() => {}).finally(() => setLoading(false)); }, []); if (loading) { return (
-
- - -
-
- {[1,2,3,4,5].map(i => ( - - ))} -
+
+
{[1,2,3,4,5].map(i => )}
); } @@ -49,22 +28,20 @@ export default function ModelsPage() { return (
-

AI 模型百科

-

- 收录主流大语言模型,全面对比各项参数,帮助你选择最适合的模型 -

+

{t.models.title}

+

{t.models.desc}

- - - - - - + + + + + + @@ -72,12 +49,8 @@ export default function ModelsPage() { @@ -110,7 +83,7 @@ export default function ModelsPage() {

{model.name}

- {model.isFree && 免费} + {model.isFree && {t.models.free}}

{model.provider}

{model.description}

@@ -120,14 +93,8 @@ export default function ModelsPage() { ))}
-
- 上下文 - {model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'} -
-
- 最大输出 - {model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'} -
+
{t.models.contextWindow}{model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'}
+
{t.models.maxOutput}{model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'}
))} diff --git a/frontend/src/app/prompts/page.tsx b/frontend/src/app/prompts/page.tsx index a600277..b831bf6 100644 --- a/frontend/src/app/prompts/page.tsx +++ b/frontend/src/app/prompts/page.tsx @@ -4,66 +4,51 @@ import { useEffect, useState } from 'react'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; -import { MessageSquare, Heart } from 'lucide-react'; +import { Heart } from 'lucide-react'; import { API_BASE } from '@/lib/config'; +import { useT } from '@/i18n'; -interface Prompt { - id: number; title: string; description: string; content: string; - model: string | null; likeCount: number; tags: string | null; -} +interface Prompt { id: number; title: string; description: string; content: string; model: string | null; likeCount: number; tags: string | null } function PromptSkeleton() { return ( -
- - -
- - - +
+
); } export default function PromptsPage() { + const t = useT(); const [prompts, setPrompts] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { - fetch(`${API_BASE}/prompts`) - .then(r => r.json()).then(data => setPrompts(data.items || [])) - .catch(() => {}).finally(() => setLoading(false)); + fetch(`${API_BASE}/prompts`).then(r => r.json()).then(data => setPrompts(data.items || [])).catch(() => {}).finally(() => setLoading(false)); }, []); return (
-

提示词库

+

{t.nav.prompts}

精选提示词模板,开箱即用

{loading ? ( -
- {[1,2,3,4].map(i => )} -
+
{[1,2,3,4].map(i => )}
) : (
{prompts.map((prompt) => (
- {prompt.tags?.split(',').slice(0, 2).map(tag => ( - {tag.trim()} - ))} - {prompt.model && ( - {prompt.model} - )} + {prompt.tags?.split(',').slice(0, 2).map(tag => {tag.trim()})} + {prompt.model && {prompt.model}}

{prompt.title}

{prompt.description || prompt.content}

- - {prompt.likeCount} + {prompt.likeCount}
))} diff --git a/frontend/src/components/layout/header.tsx b/frontend/src/components/layout/header.tsx index 72fe46e..faf280a 100644 --- a/frontend/src/components/layout/header.tsx +++ b/frontend/src/components/layout/header.tsx @@ -57,10 +57,10 @@ export function Header() { { href: '/', label: t.nav.home }, { href: '/courses', label: t.nav.courses }, { href: '/sandbox', label: t.nav.sandbox }, - { href: '/skills', label: t.discover?.skills || '技能' }, - { href: '/models', label: t.discover?.models || '模型' }, + { href: '/skills', label: t.nav.skills }, + { href: '/models', label: t.nav.models }, { href: '/prompts', label: t.nav.prompts }, - { href: '/contents', label: t.discover?.articles || '文章' }, + { href: '/contents', label: t.nav.articles }, { href: '/tools', label: t.nav.tools }, { href: '/community', label: t.nav.community }, ]; diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 8778a00..685b03d 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -2,7 +2,7 @@ import type { Translations } from './zh' const en: Translations = { common: { loading: 'Loading...', save: 'Save', cancel: 'Cancel', delete: 'Delete', confirm: 'Confirm', search: 'Search', back: 'Back', login: 'Login', register: 'Register', logout: 'Logout', retry: 'Retry', noData: 'No data', viewAll: 'View all' }, - nav: { home: 'Home', courses: 'Courses', prompts: 'Prompts', sandbox: 'AI Sandbox', discover: 'Discover', my: 'My', tools: 'Tools', community: 'Community' }, + nav: { home: 'Home', courses: 'Courses', prompts: 'Prompts', sandbox: 'AI Sandbox', discover: 'Discover', my: 'My', tools: 'Tools', community: 'Community', skills: 'Skills', models: 'Models', articles: 'Articles' }, home: { badge: 'Free AI Learning Community', heroHighlight: 'Empower Everyone', heroRest: 'to Master AI', desc: 'AI knowledge, prompt engineering, sandbox practice & model encyclopedia', startExplore: 'Get Started', freeRegister: 'Register Free', statTopics: 'AI Topics', statPrompts: 'Curated Prompts', statTools: 'AI Tool Reviews', statExplorers: 'Explorers', whyTitle: 'Why Yuzhiran?', whyDesc: 'Four core advantages to master AI fast', featureGuide: 'Guided Learning', featureGuideDesc: 'Content organized by role and scenario', featureSandbox: 'AI Sandbox', featureSandboxDesc: 'Built-in AI sandbox to learn by doing', featurePrompts: 'Prompt Library', featurePromptsDesc: '200+ curated prompt templates', featureUpdate: 'Always Up-to-date', featureUpdateDesc: 'Content updated as AI evolves', popularTopics: 'Popular Topics', popularDesc: 'From beginner to expert, explore AI systematically', moduleCount: '{n} modules', studentCount: '{n} learners', openSandbox: 'Open Sandbox', ctaTitle: 'Ready to Start Your AI Journey?', ctaDesc: 'Register now and explore everything for free' }, auth: { loginTitle: 'Login', registerTitle: 'Register', phone: 'Phone', password: 'Password', nickname: 'Nickname', welcomeBack: 'Welcome back', loginSubtitle: 'Log in to continue your AI journey', joinTitle: 'Join Yuzhiran', registerSubtitle: 'Register for free and explore AI', accountPlaceholder: 'Phone / Email', loggingIn: 'Logging in...', nicknameOptional: 'Nickname (optional)', passwordHint: 'Password (min 6 characters)', confirmPassword: 'Confirm password', registering: 'Registering...', agreePrefix: 'By registering, you agree to our', termsOfService: 'Terms of Service', privacyPolicy: 'Privacy Policy', aiAgreement: 'AI Service Agreement', fillAccountAndPassword: 'Please enter account and password', fillPhoneOrEmail: 'Please enter phone or email', fillPassword: 'Please enter password', passwordMinLength: 'Password must be at least 6 characters', passwordsNotMatch: 'Passwords do not match', loginFailed: 'Login failed', registerFailed: 'Registration failed', loginSuccess: 'Login successful', registerSuccess: 'Registration successful' }, dashboard: { title: 'My Learning', desc: 'Track your learning progress and stats', inProgressCourses: 'Courses in Progress', completedLessons: 'Lessons Completed', favoritePrompts: 'Favorite Prompts', studyDays: 'Study Days', todayLearned: "Today's Learning", tabProgress: 'Progress', tabFavorites: 'Favorites', tabProfile: 'Profile', noLearningRecords: 'No learning records yet', browseCourses: 'Browse Courses', learningProgress: 'Learning Progress', lessonCount: '{completed}/{total} lessons ({progress}%)', noFavorites: 'No favorite prompts yet', browsePrompts: 'Browse Prompts', profile: 'Profile', nicknameLabel: 'Nickname', nicknamePlaceholder: 'Enter nickname', memberPlan: 'Membership', freeUser: 'Free User', memberExpire: 'Membership Expires', joinDate: 'Joined', saveSuccess: 'Saved successfully', saveFailed: 'Save failed', loadFailed: 'Failed to load data' }, @@ -17,7 +17,7 @@ const en: Translations = { tools: { title: 'AI Tools', desc: 'Curated AI tools to boost your productivity' }, discover: { desc: 'Explore trending content and curated picks', hotCourses: 'Hot Courses', hotPrompts: 'Trending Prompts', hotPosts: 'Popular Discussions', viewCount: '{n} views', likeCount: '{n} likes', postStats: '❤️ {likes} · 👁 {views}' }, footer: { tagline: 'Empowering Everyone to Master AI', explore: 'Explore', about: 'About', aboutUs: 'About Us', privacy: 'Privacy Policy', terms: 'Terms of Service', aiAgreement: 'AI Service Agreement', contact: 'Contact', copyright: '© {year} Yuzhiran Technology Center. All rights reserved.', models: 'Models', aiTools: 'AI Tools', articles: 'Articles', skills: 'Skills' }, - models: { title: 'AI Model Encyclopedia', desc: 'Compare mainstream LLMs to find the best fit', tableName: 'Model', tableProvider: 'Provider', tableCapabilities: 'Capabilities', tableContext: 'Context', tableMaxOutput: 'Max Output', tablePricing: 'Pricing', free: 'Free', recommended: 'Recommended', pricingFree: 'Free', pricingMixed: 'Free/Paid', pricingPaid: 'Paid' }, + models: { title: 'AI Model Encyclopedia', desc: 'Compare mainstream LLMs to find the best fit', tableName: 'Model', tableProvider: 'Provider', tableCapabilities: 'Capabilities', tableContext: 'Context', tableMaxOutput: 'Max Output', tablePricing: 'Pricing', free: 'Free', recommended: 'Recommended', pricingFree: 'Free', pricingMixed: 'Free/Paid', pricingPaid: 'Paid', contextWindow: 'Context', maxOutput: 'Max Output' }, error: { title: 'Something went wrong', desc: 'Page failed to load. Please try again.', reload: 'Reload' }, notFound: { title: '404', desc: 'Page not found', backToHome: 'Back to Home' }, share: { missingToken: 'Missing share token', invalidLink: 'Invalid share link', notAvailable: 'Shared content not available', expired: 'This share link may have expired', goToSandbox: 'Go to AI Sandbox', backToSandbox: 'AI Sandbox', modelInfo: 'Model: {model} · {date}' }, diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index 5756662..17602e6 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -1,6 +1,6 @@ const zh = { common: { loading: '加载中...', save: '保存', cancel: '取消', delete: '删除', confirm: '确认', search: '搜索', back: '返回', login: '登录', register: '注册', logout: '退出登录', retry: '重试', noData: '暂无数据', viewAll: '查看全部' }, - nav: { home: '首页', courses: '课程', prompts: '提示词库', sandbox: 'AI 沙盒', discover: '发现', my: '我的', tools: '工具', community: '社区' }, + nav: { home: '首页', courses: '课程', prompts: '提示词库', sandbox: 'AI 沙盒', discover: '发现', my: '我的', tools: '工具', community: '社区', skills: '技能', models: '模型', articles: '文章' }, home: { badge: '免费 AI 知识社区', heroHighlight: '让每个人', heroRest: '都能用好 AI', desc: '涵盖 AI 通识、提示词工程、沙盒实战、模型百科', startExplore: '开始探索', freeRegister: '免费注册', statTopics: 'AI 专题', statPrompts: '精选提示词', statTools: 'AI 工具评测', statExplorers: '探索者', whyTitle: '为什么选择宇之然?', whyDesc: '四大核心优势,助你快速掌握 AI', featureGuide: '分领域指南', featureGuideDesc: '按职业和场景分类内容,学即所用', featureSandbox: 'AI 沙盒实战', featureSandboxDesc: '内置 AI 对话沙盒,边学边练', featurePrompts: '提示词库', featurePromptsDesc: '精选 200+ 提示词模板', featureUpdate: '持续更新', featureUpdateDesc: '紧跟大模型迭代,内容实时更新', popularTopics: '热门专题', popularDesc: '从入门到精通,系统探索 AI', moduleCount: '{n} 模块', studentCount: '{n} 人关注', openSandbox: '打开沙盒', ctaTitle: '准备好开启 AI 之旅了吗?', ctaDesc: '立即注册,免费探索所有内容' }, auth: { loginTitle: '登录', registerTitle: '注册', phone: '手机号', password: '密码', nickname: '昵称', welcomeBack: '欢迎回来', loginSubtitle: '登录继续你的 AI 探索之旅', joinTitle: '加入宇之然', registerSubtitle: '免费注册,开始探索 AI', accountPlaceholder: '手机号 / 邮箱', loggingIn: '登录中...', nicknameOptional: '昵称(选填)', passwordHint: '密码(至少 6 位)', confirmPassword: '确认密码', registering: '注册中...', agreePrefix: '注册即表示同意', termsOfService: '服务协议', privacyPolicy: '隐私政策', aiAgreement: 'AI 服务协议', fillAccountAndPassword: '请填写账号和密码', fillPhoneOrEmail: '请填写手机号或邮箱', fillPassword: '请填写密码', passwordMinLength: '密码至少 6 位', passwordsNotMatch: '两次密码不一致', loginFailed: '登录失败', registerFailed: '注册失败', loginSuccess: '登录成功', registerSuccess: '注册成功' }, dashboard: { title: '我的学习', desc: '掌握你的学习进度和统计', inProgressCourses: '学习中课程', completedLessons: '已完成课时', favoritePrompts: '收藏提示词', studyDays: '学习天数', todayLearned: '今日学习', tabProgress: '学习进度', tabFavorites: '收藏夹', tabProfile: '个人设置', noLearningRecords: '还没有学习记录', browseCourses: '浏览课程', learningProgress: '学习进度', lessonCount: '{completed}/{total} 课时 ({progress}%)', noFavorites: '还没有收藏的提示词', browsePrompts: '浏览提示词', profile: '个人资料', nicknameLabel: '昵称', nicknamePlaceholder: '输入昵称', memberPlan: '会员计划', freeUser: '免费用户', memberExpire: '会员到期', joinDate: '注册时间', saveSuccess: '保存成功', saveFailed: '保存失败', loadFailed: '加载数据失败' }, @@ -15,7 +15,7 @@ const zh = { tools: { title: 'AI 工具库', desc: '收录优质 AI 工具,助力工作效率提升' }, discover: { desc: '探索热门内容和精选推荐', hotCourses: '热门课程', hotPrompts: '热门提示词', hotPosts: '热门讨论', viewCount: '{n} 浏览', likeCount: '{n} 点赞', postStats: '❤️ {likes} 点赞 · 👁 {views} 浏览' }, footer: { tagline: '让每个人都能用好 AI', explore: '探索', about: '关于', aboutUs: '关于我们', privacy: '隐私政策', terms: '服务协议', aiAgreement: 'AI 服务协议', contact: '联系方式', copyright: '© {year} 北京宇之然科技中心 版权所有', models: '模型百科', aiTools: 'AI 工具', articles: '文章', skills: '技能' }, - models: { title: 'AI 模型百科', desc: '收录主流大语言模型,全面对比各项参数', tableName: '模型名称', tableProvider: '提供商', tableCapabilities: '能力', tableContext: '上下文', tableMaxOutput: '最大输出', tablePricing: '价格', free: '免费', recommended: '推荐', pricingFree: '免费', pricingMixed: '免费/付费', pricingPaid: '付费' }, + models: { title: 'AI 模型百科', desc: '收录主流大语言模型,全面对比各项参数', tableName: '模型名称', tableProvider: '提供商', tableCapabilities: '能力', tableContext: '上下文', tableMaxOutput: '最大输出', tablePricing: '价格', free: '免费', recommended: '推荐', pricingFree: '免费', pricingMixed: '免费/付费', pricingPaid: '付费', contextWindow: '上下文', maxOutput: '最大输出' }, error: { title: '出错了', desc: '页面加载失败,请稍后重试', reload: '重新加载' }, notFound: { title: '404', desc: '页面未找到', backToHome: '返回首页' }, share: { missingToken: '缺少分享参数', invalidLink: '分享链接无效', notAvailable: '分享内容不可用', expired: '该分享链接可能已过期或不存在', goToSandbox: '前往 AI 沙盒', backToSandbox: 'AI 沙盒', modelInfo: '模型: {model} · {date}' },
模型名称提供商能力上下文最大输出价格{t.models.tableName}{t.models.tableProvider}{t.models.tableCapabilities}{t.models.tableContext}{t.models.tableMaxOutput}{t.models.tablePricing}
{model.name}
- {model.isFree && ( - 免费 - )} - {model.isFeatured && !model.isFree && ( - 推荐 - )} + {model.isFree && {t.models.free}} + {model.isFeatured && !model.isFree && {t.models.recommended}}
{model.provider} @@ -95,7 +68,7 @@ export default function ModelsPage() { - {model.isFree ? '免费' : model.pricing?.includes('免费') ? '免费/付费' : '付费'} + {model.isFree ? t.models.pricingFree : model.pricing?.includes('免费') ? t.models.pricingMixed : t.models.pricingPaid}