i18n: translate frontend UI strings to English
This commit is contained in:
@@ -21,7 +21,7 @@ interface SetupForm {
|
||||
project_description: string
|
||||
}
|
||||
|
||||
const STEPS = ['欢迎', '数据库', '管理员', '项目', '完成']
|
||||
const STEPS = ['Welcome', 'Database', 'Admin', 'Projects', 'Finish']
|
||||
|
||||
export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
const [step, setStep] = useState(0)
|
||||
@@ -40,7 +40,7 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
db_database: 'harborforge',
|
||||
backend_base_url: 'http://127.0.0.1:8000',
|
||||
project_name: 'Default',
|
||||
project_description: '默认项目',
|
||||
project_description: 'Default project',
|
||||
})
|
||||
|
||||
const wizardApi = axios.create({
|
||||
@@ -59,7 +59,7 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
setStep(1)
|
||||
} catch {
|
||||
setWizardOk(false)
|
||||
setError(`无法连接 AbstractWizard (${wizardBase})。\n请确认已通过 SSH 隧道映射端口:\nssh -L <wizard_port>:127.0.0.1:<wizard_port> user@server`)
|
||||
setError(`Unable to connect to AbstractWizard (${wizardBase}).\nPlease ensure the SSH tunnel is configured:\nssh -L <wizard_port>:127.0.0.1:<wizard_port> user@server`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
|
||||
setStep(4)
|
||||
} catch (err: any) {
|
||||
setError(`保存配置失败: ${err.message}`)
|
||||
setError(`Failed to save configuration: ${err.message}`)
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
@@ -108,7 +108,7 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
<div className="setup-wizard">
|
||||
<div className="setup-container">
|
||||
<div className="setup-header">
|
||||
<h1>⚓ HarborForge 初始化向导</h1>
|
||||
<h1>⚓ HarborForge Setup Wizard</h1>
|
||||
<div className="setup-steps">
|
||||
{STEPS.map((s, i) => (
|
||||
<span key={i} className={`setup-step ${i === step ? 'active' : i < step ? 'done' : ''}`}>
|
||||
@@ -123,17 +123,17 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
{/* Step 0: Welcome */}
|
||||
{step === 0 && (
|
||||
<div className="setup-step-content">
|
||||
<h2>欢迎使用 HarborForge</h2>
|
||||
<p>Agent/人类协同任务管理平台</p>
|
||||
<h2>Welcome to HarborForge</h2>
|
||||
<p>Agent/Human collaborative task management platform</p>
|
||||
<div className="setup-info">
|
||||
<p>⚠️ 初始化向导通过 SSH 隧道连接 AbstractWizard,请确保已映射端口:</p>
|
||||
<p>⚠️ The setup wizard connects to AbstractWizard via SSH tunnel. Ensure the port is forwarded:</p>
|
||||
<code>ssh -L <wizard_port>:127.0.0.1:<wizard_port> user@your-server</code>
|
||||
</div>
|
||||
<button className="btn-primary" onClick={checkWizard}>
|
||||
连接 Wizard 开始配置
|
||||
Connect to Wizard
|
||||
</button>
|
||||
{wizardOk === false && (
|
||||
<p className="setup-hint">连接失败,请检查 SSH 隧道是否正确建立。</p>
|
||||
<p className="setup-hint">Connection failed. Check the SSH tunnel.</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -141,18 +141,18 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
{/* Step 1: Database */}
|
||||
{step === 1 && (
|
||||
<div className="setup-step-content">
|
||||
<h2>数据库配置</h2>
|
||||
<p className="text-dim">配置 MySQL 连接信息(使用 docker-compose 内置 MySQL 可保持默认值)</p>
|
||||
<h2>Database configuration</h2>
|
||||
<p className="text-dim">Configure MySQL connection (docker-compose defaults are fine if using the bundled MySQL).</p>
|
||||
<div className="setup-form">
|
||||
<label>主机 <input value={form.db_host} onChange={(e) => set('db_host', e.target.value)} /></label>
|
||||
<label>端口 <input type="number" value={form.db_port} onChange={(e) => set('db_port', Number(e.target.value))} /></label>
|
||||
<label>用户名 <input value={form.db_user} onChange={(e) => set('db_user', e.target.value)} /></label>
|
||||
<label>密码 <input type="password" value={form.db_password} onChange={(e) => set('db_password', e.target.value)} /></label>
|
||||
<label>数据库名 <input value={form.db_database} onChange={(e) => set('db_database', e.target.value)} /></label>
|
||||
<label>Host <input value={form.db_host} onChange={(e) => set('db_host', e.target.value)} /></label>
|
||||
<label>Port <input type="number" value={form.db_port} onChange={(e) => set('db_port', Number(e.target.value))} /></label>
|
||||
<label>Username <input value={form.db_user} onChange={(e) => set('db_user', e.target.value)} /></label>
|
||||
<label>Password <input type="password" value={form.db_password} onChange={(e) => set('db_password', e.target.value)} /></label>
|
||||
<label>Database <input value={form.db_database} onChange={(e) => set('db_database', e.target.value)} /></label>
|
||||
</div>
|
||||
<div className="setup-nav">
|
||||
<button className="btn-back" onClick={() => setStep(0)}>上一步</button>
|
||||
<button className="btn-primary" onClick={() => setStep(2)}>下一步</button>
|
||||
<button className="btn-back" onClick={() => setStep(0)}>Back</button>
|
||||
<button className="btn-primary" onClick={() => setStep(2)}>Next</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -160,21 +160,21 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
{/* Step 2: Admin */}
|
||||
{step === 2 && (
|
||||
<div className="setup-step-content">
|
||||
<h2>管理员账号</h2>
|
||||
<p className="text-dim">创建首个管理员用户</p>
|
||||
<h2>Admin account</h2>
|
||||
<p className="text-dim">Create the first admin user</p>
|
||||
<div className="setup-form">
|
||||
<label>用户名 <input value={form.admin_username} onChange={(e) => set('admin_username', e.target.value)} required /></label>
|
||||
<label>密码 <input type="password" value={form.admin_password} onChange={(e) => set('admin_password', e.target.value)} required placeholder="设置管理员密码" /></label>
|
||||
<label>邮箱 <input type="email" value={form.admin_email} onChange={(e) => set('admin_email', e.target.value)} placeholder="admin@example.com" /></label>
|
||||
<label>姓名 <input value={form.admin_full_name} onChange={(e) => set('admin_full_name', e.target.value)} /></label>
|
||||
<label>Username <input value={form.admin_username} onChange={(e) => set('admin_username', e.target.value)} required /></label>
|
||||
<label>Password <input type="password" value={form.admin_password} onChange={(e) => set('admin_password', e.target.value)} required placeholder="Set admin password" /></label>
|
||||
<label>Email <input type="email" value={form.admin_email} onChange={(e) => set('admin_email', e.target.value)} placeholder="admin@example.com" /></label>
|
||||
<label>Full name <input value={form.admin_full_name} onChange={(e) => set('admin_full_name', e.target.value)} /></label>
|
||||
</div>
|
||||
<div className="setup-nav">
|
||||
<button className="btn-back" onClick={() => setStep(1)}>上一步</button>
|
||||
<button className="btn-back" onClick={() => setStep(1)}>Back</button>
|
||||
<button className="btn-primary" onClick={() => {
|
||||
if (!form.admin_password) { setError('请设置管理员密码'); return }
|
||||
if (!form.admin_password) { setError('Please set an admin password'); return }
|
||||
setError('')
|
||||
setStep(3)
|
||||
}}>下一步</button>
|
||||
}}>Next</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -182,17 +182,17 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
{/* Step 3: Project */}
|
||||
{step === 3 && (
|
||||
<div className="setup-step-content">
|
||||
<h2>默认项目(可选)</h2>
|
||||
<p className="text-dim">创建一个初始项目,也可以跳过</p>
|
||||
<h2>Default project (optional)</h2>
|
||||
<p className="text-dim">Create an initial project or skip</p>
|
||||
<div className="setup-form">
|
||||
<label>后端 Base URL <input value={form.backend_base_url} onChange={(e) => set('backend_base_url', e.target.value)} placeholder="http://127.0.0.1:8000" /></label>
|
||||
<label>项目名称 <input value={form.project_name} onChange={(e) => set('project_name', e.target.value)} placeholder="留空则跳过" /></label>
|
||||
<label>项目描述 <input value={form.project_description} onChange={(e) => set('project_description', e.target.value)} /></label>
|
||||
<label>Backend Base URL <input value={form.backend_base_url} onChange={(e) => set('backend_base_url', e.target.value)} placeholder="http://127.0.0.1:8000" /></label>
|
||||
<label>Project name <input value={form.project_name} onChange={(e) => set('project_name', e.target.value)} placeholder="Leave blank to skip" /></label>
|
||||
<label>ProjectsDescription <input value={form.project_description} onChange={(e) => set('project_description', e.target.value)} /></label>
|
||||
</div>
|
||||
<div className="setup-nav">
|
||||
<button className="btn-back" onClick={() => setStep(2)}>上一步</button>
|
||||
<button className="btn-back" onClick={() => setStep(2)}>Back</button>
|
||||
<button className="btn-primary" onClick={saveConfig} disabled={saving}>
|
||||
{saving ? '保存中...' : '完成配置'}
|
||||
{saving ? 'Saving...' : 'Finish setup'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -202,16 +202,16 @@ export default function SetupWizardPage({ wizardBase, onComplete }: Props) {
|
||||
{step === 4 && (
|
||||
<div className="setup-step-content">
|
||||
<div className="setup-done">
|
||||
<h2>✅ 初始化完成!</h2>
|
||||
<p>配置已保存到 AbstractWizard。</p>
|
||||
<h2>✅ Setup complete!</h2>
|
||||
<p>Configuration saved to AbstractWizard.</p>
|
||||
<div className="setup-info">
|
||||
<p>请在服务器上重启服务:</p>
|
||||
<p>Restart services on the server:</p>
|
||||
<code>docker compose restart</code>
|
||||
<p style={{ marginTop: '1rem' }}>后端启动完成后,刷新本页面进入登录界面。</p>
|
||||
<p>管理员账号: <strong>{form.admin_username}</strong></p>
|
||||
<p style={{ marginTop: '1rem' }}>After the backend starts, refresh this page to go to login.</p>
|
||||
<p>Admin account: <strong>{form.admin_username}</strong></p>
|
||||
</div>
|
||||
<button className="btn-primary" onClick={onComplete}>
|
||||
刷新检查
|
||||
Refresh to check
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user