fix: 导航 i18n 补全 + 模型/提示词页 useT()
- Header 导航 skills/models/articles 改为 t.nav.*(英文正常显示) - 模型百科页全部文字使用 useT()(表格标题、标签等) - 提示词库页标题使用 useT() - models 翻译键补全 contextWindow/maxOutput
This commit is contained in:
@@ -3,45 +3,24 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { API_BASE } from '@/lib/config';
|
import { API_BASE } from '@/lib/config';
|
||||||
|
import { useT } from '@/i18n';
|
||||||
|
|
||||||
interface AiModel {
|
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 }
|
||||||
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() {
|
export default function ModelsPage() {
|
||||||
|
const t = useT();
|
||||||
const [models, setModels] = useState<AiModel[]>([]);
|
const [models, setModels] = useState<AiModel[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch(`${API_BASE}/models`)
|
fetch(`${API_BASE}/models`).then(r => r.json()).then(setModels).catch(() => {}).finally(() => setLoading(false));
|
||||||
.then(r => r.json())
|
|
||||||
.then(setModels)
|
|
||||||
.catch(() => {})
|
|
||||||
.finally(() => setLoading(false));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12"><Skeleton className="h-9 w-48 mx-auto mb-3" /><Skeleton className="h-5 w-96 mx-auto" /></div>
|
||||||
<Skeleton className="h-9 w-48 mx-auto mb-3" />
|
<div className="space-y-3">{[1,2,3,4,5].map(i => <Skeleton key={i} className="h-16 w-full rounded-xl" />)}</div>
|
||||||
<Skeleton className="h-5 w-96 mx-auto" />
|
|
||||||
</div>
|
|
||||||
<div className="space-y-3">
|
|
||||||
{[1,2,3,4,5].map(i => (
|
|
||||||
<Skeleton key={i} className="h-16 w-full rounded-xl" />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -49,22 +28,20 @@ export default function ModelsPage() {
|
|||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<h1 className="text-3xl font-bold text-foreground">AI 模型百科</h1>
|
<h1 className="text-3xl font-bold text-foreground">{t.models.title}</h1>
|
||||||
<p className="mt-3 text-muted-foreground max-w-2xl mx-auto">
|
<p className="mt-3 text-muted-foreground max-w-2xl mx-auto">{t.models.desc}</p>
|
||||||
收录主流大语言模型,全面对比各项参数,帮助你选择最适合的模型
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full text-sm">
|
<table className="w-full text-sm">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="border-b border-border">
|
<tr className="border-b border-border">
|
||||||
<th className="text-left py-4 px-4 font-semibold text-foreground">模型名称</th>
|
<th className="text-left py-4 px-4 font-semibold text-foreground">{t.models.tableName}</th>
|
||||||
<th className="text-left py-4 px-4 font-semibold text-foreground">提供商</th>
|
<th className="text-left py-4 px-4 font-semibold text-foreground">{t.models.tableProvider}</th>
|
||||||
<th className="text-left py-4 px-4 font-semibold text-foreground hidden md:table-cell">能力</th>
|
<th className="text-left py-4 px-4 font-semibold text-foreground hidden md:table-cell">{t.models.tableCapabilities}</th>
|
||||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">上下文</th>
|
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">{t.models.tableContext}</th>
|
||||||
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">最大输出</th>
|
<th className="text-right py-4 px-4 font-semibold text-foreground hidden lg:table-cell">{t.models.tableMaxOutput}</th>
|
||||||
<th className="text-center py-4 px-4 font-semibold text-foreground hidden sm:table-cell">价格</th>
|
<th className="text-center py-4 px-4 font-semibold text-foreground hidden sm:table-cell">{t.models.tablePricing}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -72,12 +49,8 @@ export default function ModelsPage() {
|
|||||||
<tr key={model.id} className="border-b border-border hover:bg-accent/50 transition-colors">
|
<tr key={model.id} className="border-b border-border hover:bg-accent/50 transition-colors">
|
||||||
<td className="py-4 px-4">
|
<td className="py-4 px-4">
|
||||||
<div className="font-semibold text-foreground">{model.name}</div>
|
<div className="font-semibold text-foreground">{model.name}</div>
|
||||||
{model.isFree && (
|
{model.isFree && <span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">{t.models.free}</span>}
|
||||||
<span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">免费</span>
|
{model.isFeatured && !model.isFree && <span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-brand-100 text-brand-700 rounded">{t.models.recommended}</span>}
|
||||||
)}
|
|
||||||
{model.isFeatured && !model.isFree && (
|
|
||||||
<span className="inline-block mt-1 text-xs px-1.5 py-0.5 bg-brand-100 text-brand-700 rounded">推荐</span>
|
|
||||||
)}
|
|
||||||
</td>
|
</td>
|
||||||
<td className="py-4 px-4 text-muted-foreground">{model.provider}</td>
|
<td className="py-4 px-4 text-muted-foreground">{model.provider}</td>
|
||||||
<td className="py-4 px-4 text-muted-foreground hidden md:table-cell max-w-xs">
|
<td className="py-4 px-4 text-muted-foreground hidden md:table-cell max-w-xs">
|
||||||
@@ -95,7 +68,7 @@ export default function ModelsPage() {
|
|||||||
</td>
|
</td>
|
||||||
<td className="py-4 px-4 text-center hidden sm:table-cell">
|
<td className="py-4 px-4 text-center hidden sm:table-cell">
|
||||||
<span className={`text-xs px-2 py-1 rounded ${model.isFree ? 'bg-green-100 text-green-700' : 'bg-orange-100 text-orange-700'}`}>
|
<span className={`text-xs px-2 py-1 rounded ${model.isFree ? 'bg-green-100 text-green-700' : 'bg-orange-100 text-orange-700'}`}>
|
||||||
{model.isFree ? '免费' : model.pricing?.includes('免费') ? '免费/付费' : '付费'}
|
{model.isFree ? t.models.pricingFree : model.pricing?.includes('免费') ? t.models.pricingMixed : t.models.pricingPaid}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -110,7 +83,7 @@ export default function ModelsPage() {
|
|||||||
<div key={`card-${model.id}`} className="bg-card rounded-xl border border-border p-6 hover:border-brand-200 transition-colors">
|
<div key={`card-${model.id}`} className="bg-card rounded-xl border border-border p-6 hover:border-brand-200 transition-colors">
|
||||||
<div className="flex items-start justify-between mb-3">
|
<div className="flex items-start justify-between mb-3">
|
||||||
<h3 className="font-semibold text-foreground">{model.name}</h3>
|
<h3 className="font-semibold text-foreground">{model.name}</h3>
|
||||||
{model.isFree && <span className="text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">免费</span>}
|
{model.isFree && <span className="text-xs px-1.5 py-0.5 bg-green-100 text-green-700 rounded">{t.models.free}</span>}
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground mb-3">{model.provider}</p>
|
<p className="text-sm text-muted-foreground mb-3">{model.provider}</p>
|
||||||
<p className="text-sm text-muted-foreground line-clamp-2">{model.description}</p>
|
<p className="text-sm text-muted-foreground line-clamp-2">{model.description}</p>
|
||||||
@@ -120,14 +93,8 @@ export default function ModelsPage() {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 pt-4 border-t border-border grid grid-cols-2 gap-3 text-xs text-muted-foreground">
|
<div className="mt-4 pt-4 border-t border-border grid grid-cols-2 gap-3 text-xs text-muted-foreground">
|
||||||
<div>
|
<div><span className="block text-muted-foreground">{t.models.contextWindow}</span>{model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'}</div>
|
||||||
<span className="block text-muted-foreground">上下文</span>
|
<div><span className="block text-muted-foreground">{t.models.maxOutput}</span>{model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'}</div>
|
||||||
{model.contextWindow ? `${(model.contextWindow / 1000).toFixed(0)}K tokens` : '-'}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span className="block text-muted-foreground">最大输出</span>
|
|
||||||
{model.maxTokens ? `${(model.maxTokens / 1024).toFixed(0)}K tokens` : '-'}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -4,66 +4,51 @@ import { useEffect, useState } from 'react';
|
|||||||
import { Card } from '@/components/ui/card';
|
import { Card } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/ui/skeleton';
|
||||||
import { MessageSquare, Heart } from 'lucide-react';
|
import { Heart } from 'lucide-react';
|
||||||
import { API_BASE } from '@/lib/config';
|
import { API_BASE } from '@/lib/config';
|
||||||
|
import { useT } from '@/i18n';
|
||||||
|
|
||||||
interface Prompt {
|
interface Prompt { id: number; title: string; description: string; content: string; model: string | null; likeCount: number; tags: string | null }
|
||||||
id: number; title: string; description: string; content: string;
|
|
||||||
model: string | null; likeCount: number; tags: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function PromptSkeleton() {
|
function PromptSkeleton() {
|
||||||
return (
|
return (
|
||||||
<Card className="p-5">
|
<Card className="p-5">
|
||||||
<div className="flex gap-2 mb-2">
|
<div className="flex gap-2 mb-2"><Skeleton className="h-5 w-16 rounded-full" /><Skeleton className="h-5 w-20 rounded-full" /></div>
|
||||||
<Skeleton className="h-5 w-16 rounded-full" />
|
<Skeleton className="h-5 w-3/4 mb-1" /><Skeleton className="h-4 w-full mb-2" /><Skeleton className="h-4 w-16" />
|
||||||
<Skeleton className="h-5 w-20 rounded-full" />
|
|
||||||
</div>
|
|
||||||
<Skeleton className="h-5 w-3/4 mb-1" />
|
|
||||||
<Skeleton className="h-4 w-full mb-2" />
|
|
||||||
<Skeleton className="h-4 w-16" />
|
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PromptsPage() {
|
export default function PromptsPage() {
|
||||||
|
const t = useT();
|
||||||
const [prompts, setPrompts] = useState<Prompt[]>([]);
|
const [prompts, setPrompts] = useState<Prompt[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch(`${API_BASE}/prompts`)
|
fetch(`${API_BASE}/prompts`).then(r => r.json()).then(data => setPrompts(data.items || [])).catch(() => {}).finally(() => setLoading(false));
|
||||||
.then(r => r.json()).then(data => setPrompts(data.items || []))
|
|
||||||
.catch(() => {}).finally(() => setLoading(false));
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||||
<div className="mb-10">
|
<div className="mb-10">
|
||||||
<h1 className="text-3xl font-bold text-foreground">提示词库</h1>
|
<h1 className="text-3xl font-bold text-foreground">{t.nav.prompts}</h1>
|
||||||
<p className="mt-2 text-muted-foreground">精选提示词模板,开箱即用</p>
|
<p className="mt-2 text-muted-foreground">精选提示词模板,开箱即用</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">{[1,2,3,4].map(i => <PromptSkeleton key={i} />)}</div>
|
||||||
{[1,2,3,4].map(i => <PromptSkeleton key={i} />)}
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
{prompts.map((prompt) => (
|
{prompts.map((prompt) => (
|
||||||
<Card key={prompt.id} className="p-5 hover:shadow-md transition-shadow group">
|
<Card key={prompt.id} className="p-5 hover:shadow-md transition-shadow group">
|
||||||
<div className="flex items-center gap-2 mb-2 flex-wrap">
|
<div className="flex items-center gap-2 mb-2 flex-wrap">
|
||||||
{prompt.tags?.split(',').slice(0, 2).map(tag => (
|
{prompt.tags?.split(',').slice(0, 2).map(tag => <Badge key={tag} variant="default">{tag.trim()}</Badge>)}
|
||||||
<Badge key={tag} variant="default">{tag.trim()}</Badge>
|
{prompt.model && <span className="text-xs text-muted-foreground ml-auto">{prompt.model}</span>}
|
||||||
))}
|
|
||||||
{prompt.model && (
|
|
||||||
<span className="text-xs text-muted-foreground ml-auto">{prompt.model}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<h3 className="font-semibold group-hover:text-brand-600 transition-colors mb-1">{prompt.title}</h3>
|
<h3 className="font-semibold group-hover:text-brand-600 transition-colors mb-1">{prompt.title}</h3>
|
||||||
<p className="text-sm text-muted-foreground mb-3 line-clamp-2">{prompt.description || prompt.content}</p>
|
<p className="text-sm text-muted-foreground mb-3 line-clamp-2">{prompt.description || prompt.content}</p>
|
||||||
<div className="flex items-center gap-1 text-sm text-muted-foreground">
|
<div className="flex items-center gap-1 text-sm text-muted-foreground">
|
||||||
<Heart className="w-3.5 h-3.5" />
|
<Heart className="w-3.5 h-3.5" /><span>{prompt.likeCount}</span>
|
||||||
<span>{prompt.likeCount}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -57,10 +57,10 @@ export function Header() {
|
|||||||
{ href: '/', label: t.nav.home },
|
{ href: '/', label: t.nav.home },
|
||||||
{ href: '/courses', label: t.nav.courses },
|
{ href: '/courses', label: t.nav.courses },
|
||||||
{ href: '/sandbox', label: t.nav.sandbox },
|
{ href: '/sandbox', label: t.nav.sandbox },
|
||||||
{ href: '/skills', label: t.discover?.skills || '技能' },
|
{ href: '/skills', label: t.nav.skills },
|
||||||
{ href: '/models', label: t.discover?.models || '模型' },
|
{ href: '/models', label: t.nav.models },
|
||||||
{ href: '/prompts', label: t.nav.prompts },
|
{ 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: '/tools', label: t.nav.tools },
|
||||||
{ href: '/community', label: t.nav.community },
|
{ href: '/community', label: t.nav.community },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type { Translations } from './zh'
|
|||||||
|
|
||||||
const en: Translations = {
|
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' },
|
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' },
|
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' },
|
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' },
|
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' },
|
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}' },
|
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' },
|
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' },
|
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' },
|
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}' },
|
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}' },
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const zh = {
|
const zh = {
|
||||||
common: { loading: '加载中...', save: '保存', cancel: '取消', delete: '删除', confirm: '确认', search: '搜索', back: '返回', login: '登录', register: '注册', logout: '退出登录', retry: '重试', noData: '暂无数据', viewAll: '查看全部' },
|
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: '立即注册,免费探索所有内容' },
|
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: '注册成功' },
|
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: '加载数据失败' },
|
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 工具,助力工作效率提升' },
|
tools: { title: 'AI 工具库', desc: '收录优质 AI 工具,助力工作效率提升' },
|
||||||
discover: { desc: '探索热门内容和精选推荐', hotCourses: '热门课程', hotPrompts: '热门提示词', hotPosts: '热门讨论', viewCount: '{n} 浏览', likeCount: '{n} 点赞', postStats: '❤️ {likes} 点赞 · 👁 {views} 浏览' },
|
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: '技能' },
|
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: '重新加载' },
|
error: { title: '出错了', desc: '页面加载失败,请稍后重试', reload: '重新加载' },
|
||||||
notFound: { title: '404', desc: '页面未找到', backToHome: '返回首页' },
|
notFound: { title: '404', desc: '页面未找到', backToHome: '返回首页' },
|
||||||
share: { missingToken: '缺少分享参数', invalidLink: '分享链接无效', notAvailable: '分享内容不可用', expired: '该分享链接可能已过期或不存在', goToSandbox: '前往 AI 沙盒', backToSandbox: 'AI 沙盒', modelInfo: '模型: {model} · {date}' },
|
share: { missingToken: '缺少分享参数', invalidLink: '分享链接无效', notAvailable: '分享内容不可用', expired: '该分享链接可能已过期或不存在', goToSandbox: '前往 AI 沙盒', backToSandbox: 'AI 沙盒', modelInfo: '模型: {model} · {date}' },
|
||||||
|
|||||||
Reference in New Issue
Block a user