feat: full i18n support - all pages use Lang.t() for zh/en

This commit is contained in:
2026-07-27 20:31:41 +08:00
parent 860bc015e8
commit de58a1c42f
10 changed files with 578 additions and 282 deletions
+10 -10
View File
@@ -15,10 +15,10 @@ const PageRecord = {
const list = await res.json();
const el = document.getElementById('rec-file-list');
if (!el) return;
if (!list.length) { el.innerHTML = '<p style="color:var(--text-tertiary);font-size:13px;padding:20px">暂无录制文件</p>'; return; }
if (!list.length) { el.innerHTML = '<p style="color:var(--text-tertiary);font-size:13px;padding:20px">' + Lang.t('noRecordings') + '</p>'; return; }
el.innerHTML = list.map(f => {
const size = f.size > 1048576 ? (f.size/1048576).toFixed(1)+'MB' : (f.size/1024).toFixed(1)+'KB';
return '<div class="glass-card" style="padding:10px 14px;margin-bottom:6px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap"><span style="font-size:12px;flex:1;min-width:150px">' + f.name + '</span><span style="font-size:11px;color:var(--text-tertiary)">' + size + '</span><button class="btn btn-sm btn-primary btn-play-rec" data-file="' + f.name + '">播放</button><a class="btn btn-sm btn-secondary" href="/api/recording/' + f.name + '/export" download>导出</a><button class="btn btn-sm btn-danger btn-del-rec" data-file="' + f.name + '">删除</button></div>';
return '<div class="glass-card" style="padding:10px 14px;margin-bottom:6px;display:flex;align-items:center;justify-content:space-between;gap:8px;flex-wrap:wrap"><span style="font-size:12px;flex:1;min-width:150px">' + f.name + '</span><span style="font-size:11px;color:var(--text-tertiary)">' + size + '</span><button class="btn btn-sm btn-primary btn-play-rec" data-file="' + f.name + '">' + Lang.t('play') + '</button><a class="btn btn-sm btn-secondary" href="/api/recording/' + f.name + '/export" download>' + Lang.t('export') + '</a><button class="btn btn-sm btn-danger btn-del-rec" data-file="' + f.name + '">' + Lang.t('delete') + '</button></div>';
}).join('');
} catch (e) { console.error(e); }
},
@@ -42,14 +42,14 @@ const PageRecord = {
const file = e.target.files[0]; if (!file) return;
const fd = new FormData(); fd.append('file', file);
await fetch('/api/recording/import', { method: 'POST', body: fd });
Toast.show('导入成功', 'success'); this._loadRecordings();
Toast.show(Lang.t('importSuccess'), 'success'); this._loadRecordings();
}; input.click();
});
document.getElementById('rec-file-list')?.addEventListener('click', async (e) => {
const playBtn = e.target.closest('.btn-play-rec');
const delBtn = e.target.closest('.btn-del-rec');
if (playBtn) this._playRecording(playBtn.dataset.file);
if (delBtn && confirm('删除?')) {
if (delBtn && confirm(Lang.t('confirmDelete'))) {
await fetch('/api/recording/' + delBtn.dataset.file + '/delete', { method: 'DELETE' });
this._loadRecordings();
}
@@ -63,24 +63,24 @@ const PageRecord = {
_updateRecUI(recording) {
document.getElementById('btn-rec-start').style.display = recording ? 'none' : '';
document.getElementById('btn-rec-stop').style.display = recording ? '' : 'none';
document.getElementById('rec-status').textContent = recording ? '录制中...' : '就绪';
document.getElementById('rec-status').textContent = recording ? Lang.t('recording') : Lang.t('ready');
},
async _playRecording(filename) {
document.getElementById('playback-file').textContent = filename;
document.getElementById('playback-bar').style.display = 'flex';
await fetch('/api/playback/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename }) });
Toast.show('回放已开始,打开仪表盘查看数据', 'info');
Toast.show(Lang.t('playbackStartedHint'), 'info');
},
_template() {
return '<div class="animated"><h2 style="font-size:24px;font-weight:700;margin-bottom:8px">录制与回放</h2><p style="color:var(--text-secondary);margin-bottom:20px">录制原始 UDP 流到 .tsr 文件,回放调试仪表盘</p>' +
return '<div class="animated"><h2 style="font-size:24px;font-weight:700;margin-bottom:8px">' + Lang.t('recordPage') + '</h2><p style="color:var(--text-secondary);margin-bottom:20px">' + Lang.t('recordDesc') + '</p>' +
'<div class="glass-card" style="padding:20px;margin-bottom:20px"><h3 style="font-size:16px;margin-bottom:12px">录制控制</h3><div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><button id="btn-rec-start" class="btn btn-primary">开始录制</button><button id="btn-rec-stop" class="btn btn-danger" style="display:none">停止录制</button><span id="rec-status" style="font-size:13px;color:var(--text-secondary)">就绪</span><span style="flex:1"></span><label class="switch-label"><input type="checkbox" id="rec-auto-mode"><span class="switch-track"></span> 自动检测</label></div></div>' +
'<div class="glass-card" style="padding:20px;margin-bottom:20px"><h3 style="font-size:16px;margin-bottom:12px">' + Lang.t('recordControl') + '</h3><div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap"><button id="btn-rec-start" class="btn btn-primary">' + Lang.t('startRecord') + '</button><button id="btn-rec-stop" class="btn btn-danger" style="display:none">' + Lang.t('stopRecord') + '</button><span id="rec-status" style="font-size:13px;color:var(--text-secondary)">' + Lang.t('ready') + '</span><span style="flex:1"></span><label class="switch-label"><input type="checkbox" id="rec-auto-mode"><span class="switch-track"></span> ' + Lang.t('autoDetect') + '</label></div></div>' +
'<div id="playback-bar" class="glass-card" style="padding:12px 20px;margin-bottom:20px;display:none;align-items:center;gap:12px;background:var(--accent-container)"><span style="font-size:13px">正在回放: <strong id="playback-file">-</strong></span><span style="flex:1"></span><span style="font-size:12px;color:var(--text-tertiary)">打开仪表盘页面即可看到数据</span><button id="btn-playback-stop" class="btn btn-sm btn-danger">停止</button></div>' +
'<div id="playback-bar" class="glass-card" style="padding:12px 20px;margin-bottom:20px;display:none;align-items:center;gap:12px;background:var(--accent-container)"><span style="font-size:13px">' + Lang.t('playbackActive') + '<strong id="playback-file">-</strong></span><span style="flex:1"></span><span style="font-size:12px;color:var(--text-tertiary)">' + Lang.t('playbackHint') + '</span><button id="btn-playback-stop" class="btn btn-sm btn-danger">' + Lang.t('stopPlayback') + '</button></div>' +
'<div class="glass-card" style="padding:20px"><h3 style="font-size:16px;margin-bottom:12px">录制文件</h3><div style="display:flex;gap:8px;margin-bottom:12px"><button id="btn-import-rec" class="btn btn-sm btn-secondary">导入 .tsr</button></div><div id="rec-file-list"></div></div>' +
'<div class="glass-card" style="padding:20px"><h3 style="font-size:16px;margin-bottom:12px">' + Lang.t('recordFiles') + '</h3><div style="display:flex;gap:8px;margin-bottom:12px"><button id="btn-import-rec" class="btn btn-sm btn-secondary">' + Lang.t('importTsr') + '</button></div><div id="rec-file-list"></div></div>' +
'</div>';
}