i18n slice 1 release C: storage, sharing, sign-in, guest, catch-all and debug pages in English
- 11 templates converted (storage, storage_network, storage_init, storage_attach, sharing, login,
claim, launcher_shared, launcher_share_password, catchall, debug); every key translated.
Six ASCII-only Hungarian JS fragments the extractor missed were found by eye and converted by hand
(", majd a(z)", "FIGYELEM:", "jelenlegi:", "mp", "p", " db").
- login, claim, both guest share pages and the catch-all render through executeTemplateLang (the
household language; no session CSRF, no escrow reminder). renderLogin now takes the request.
- Page titles: TitleKey for storage, network storage, the two drive wizards and sharing.
TestHandlerTitleKeysMatchHungarianTitle pins handler literal == hu.json value for every TitleKey.
- Tests: TestDirectRenderHandlersFollowLanguage (real routes, en + hu),
TestI18nDirectRenderPagesHaveNoAdminChrome (escrow reminder due; none on the guest page).
- Fixture correction: the release C cases had invented page titles; the cases now carry the handlers'
real titles (and the wizard pages their real page name), and those 12 fixtures were RE-CAPTURED from
the unconverted templates at 0555091. The diff to the old fixtures is the <title> line (and the nav
highlight on the two wizard pages) only.
- i18n gate: HU_FORMAL_CEILING 12 -> 16 — four more „ön" forms in the converted copy, unchanged by rule (R-516).
Hungarian: byte-identical (TestI18nParity against fixtures from unconverted templates).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -3,58 +3,55 @@
|
||||
|
||||
<div class="page-header">
|
||||
<div style="display:flex;align-items:center;gap:.5rem">
|
||||
<a href="/storage" class="btn btn-sm btn-outline">← Vissza</a>
|
||||
<h2>Új meghajtó inicializálása</h2>
|
||||
<a href="/storage" class="btn btn-sm btn-outline">{{T "storage_init.vissza"}}</a>
|
||||
<h2>{{T "storage_init.uj_meghajto_inicializalasa"}}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-card">
|
||||
<h3>1. Meghajtó kiválasztása</h3>
|
||||
<p class="settings-card-desc">Válassza ki a formázandó <strong>felhasználói adatmeghajtót</strong>. Rendszer- és
|
||||
biztonsági-mentés meghajtók itt nem jelennek meg — azok védettek. Ha a meghajtó adatot tartalmaz, a törlést
|
||||
Önnek meg kell erősítenie.</p>
|
||||
<h3>{{T "storage_init.1_meghajto_kivalasztasa"}}</h3>
|
||||
<p class="settings-card-desc">{{T "storage_init.valassza_ki_a_formazando_felhasznaloi"}}</p>
|
||||
<div id="disk-error" class="alert alert-error" style="display:none;margin-bottom:1rem"></div>
|
||||
<div id="disk-list">Betöltés…</div>
|
||||
<div id="disk-list">{{T "storage_init.betoltes"}}</div>
|
||||
</div>
|
||||
|
||||
<div class="settings-card" id="cfg-card" style="display:none">
|
||||
<h3>2. Konfiguráció</h3>
|
||||
<h3>{{T "storage_init.2_konfiguracio"}}</h3>
|
||||
<form id="init-form" onsubmit="return submitInit(event)">
|
||||
<div class="form-group">
|
||||
<label>Kiválasztott eszköz</label>
|
||||
<label>{{T "storage_init.kivalasztott_eszkoz"}}</label>
|
||||
<span class="settings-value mono" id="sel-device">—</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mount-name">Csatlakoztatási név <span class="required">*</span></label>
|
||||
<label for="mount-name">{{T "storage_init.csatlakoztatasi_nev"}} <span class="required">*</span></label>
|
||||
<div style="display:flex;align-items:center;gap:.25rem">
|
||||
<span class="mono" style="opacity:.6">/mnt/</span>
|
||||
<input type="text" id="mount-name" class="form-control" placeholder="hdd_1"
|
||||
pattern="[a-zA-Z0-9_-]+" required style="max-width:180px">
|
||||
</div>
|
||||
<span class="form-hint">A meghajtó a /mnt/<név> útvonalra kerül.</span>
|
||||
<span class="form-hint">{{T "storage_init.a_meghajto_a_mnt_nev"}}</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="fstype">Fájlrendszer</label>
|
||||
<label for="fstype">{{T "storage_init.fajlrendszer"}}</label>
|
||||
<select id="fstype" class="form-control" style="max-width:180px">
|
||||
<option value="ext4" selected>ext4</option>
|
||||
<option value="xfs">xfs</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="storage-label">Megnevezés</label>
|
||||
<input type="text" id="storage-label" class="form-control" placeholder="Külső HDD 1TB" maxlength="50">
|
||||
<label for="storage-label">{{T "storage_init.megnevezes"}}</label>
|
||||
<input type="text" id="storage-label" class="form-control" placeholder="{{T "storage_init.kulso_hdd_1tb"}}" maxlength="50">
|
||||
</div>
|
||||
<label class="toggle" style="margin-bottom:1.25rem">
|
||||
<input type="checkbox" id="set-default" checked>
|
||||
<span class="toggle-label">Beállítás alapértelmezett adattárolóként új telepítéseknél</span>
|
||||
<span class="toggle-label">{{T "storage_init.beallitas_alapertelmezett_adattarolokent"}}</span>
|
||||
</label>
|
||||
<div class="alert alert-warning" id="warn-databearing" style="display:none;margin-bottom:1rem">
|
||||
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> A kiválasztott meghajtó <strong>adatot tartalmaz</strong>. Az inicializálás (formázás) törli a rajta lévő
|
||||
összes adatot — a folytatáshoz meg kell erősítenie.
|
||||
<svg class="ico ico-sm"><use href="#i-triangle-alert"/></svg> {{T "storage_init.a_kivalasztott_meghajto_adatot_tartalmaz"}}
|
||||
</div>
|
||||
<div class="form-actions" style="gap:.75rem">
|
||||
<button type="submit" class="btn btn-danger-outline" id="init-btn">Inicializálás indítása</button>
|
||||
<a href="/settings" class="btn btn-outline">Mégsem</a>
|
||||
<button type="submit" class="btn btn-danger-outline" id="init-btn">{{T "storage_init.inicializalas_inditasa"}}</button>
|
||||
<a href="/settings" class="btn btn-outline">{{T "storage_init.megsem"}}</a>
|
||||
</div>
|
||||
<div id="init-result" style="margin-top:1rem"></div>
|
||||
</form>
|
||||
@@ -66,8 +63,8 @@ function esc(s){ return String(s==null?'':s).replace(/[&<>"]/g,function(c){retur
|
||||
|
||||
function dataBadge(d){
|
||||
return d.data_bearing
|
||||
? '<span class="badge badge-error">Adatot tartalmaz — a formázás törli</span>'
|
||||
: '<span class="badge badge-ok">Üres — formázható</span>';
|
||||
? '<span class="badge badge-error">{{T "storage_init.adatot_tartalmaz_a_formazas_torli"}}</span>'
|
||||
: '<span class="badge badge-ok">{{T "storage_init.ures_formazhato"}}</span>';
|
||||
}
|
||||
function fmtSize(b){
|
||||
if(!b) return '';
|
||||
@@ -81,15 +78,15 @@ async function loadDisks(){
|
||||
// unclaimed-disk filter already excludes OS/enrolled/claimed disks (fail-safe), so we trust the list
|
||||
// as-is — no client-side filtering. `initialize` = every unclaimed disk (blank or data-bearing).
|
||||
var r = await fetch('/api/disks/candidates'); var j = await r.json();
|
||||
if(!j.ok){ throw new Error(j.error||'Hiba'); }
|
||||
if(!j.ok){ throw new Error(j.error||'{{T "storage_init.hiba"}}'); }
|
||||
var cands = (j.data&&j.data.initialize)||[];
|
||||
if(cands.length===0){ document.getElementById('disk-list').innerHTML='<p class="form-hint">Nincs elérhető meghajtó az inicializáláshoz. Csatlakoztasson egy új adathordozót — a rendszer-, a biztonsági mentés- és a már használatban lévő meghajtók itt nem jelennek meg.</p>'; return; }
|
||||
if(cands.length===0){ document.getElementById('disk-list').innerHTML='<p class="form-hint">{{T "storage_init.nincs_elerheto_meghajto_az_inicializalas"}}</p>'; return; }
|
||||
var html='<div class="drive-list">';
|
||||
cands.forEach(function(d,i){
|
||||
var title = d.model ? esc(d.model) : esc(d.device);
|
||||
var parts = [esc(d.device)];
|
||||
if(d.size_bytes) parts.push(fmtSize(d.size_bytes));
|
||||
if(d.fstype) parts.push('jelenlegi: '+esc(d.fstype));
|
||||
if(d.fstype) parts.push('{{T "storage_init.jelenlegi"}} '+esc(d.fstype));
|
||||
var sub = parts.join(' · ');
|
||||
html+='<label class="drive-card role-user-data is-selectable" id="dc-'+i+'">'
|
||||
+'<div class="drive-card-top"><div class="drive-select"><input type="radio" name="disk" value="'+esc(d.device)+'" data-db="'+(d.data_bearing?'1':'0')+'" data-i="'+i+'" onchange="pickDisk(this)">'
|
||||
@@ -98,7 +95,7 @@ async function loadDisks(){
|
||||
});
|
||||
html+='</div>';
|
||||
document.getElementById('disk-list').innerHTML=html;
|
||||
}catch(e){ var el=document.getElementById('disk-error'); el.style.display='block'; el.textContent='Meghajtók betöltése sikertelen: '+e.message; }
|
||||
}catch(e){ var el=document.getElementById('disk-error'); el.style.display='block'; el.textContent='{{T "storage_init.meghajtok_betoltese_sikertelen"}} '+e.message; }
|
||||
}
|
||||
|
||||
function pickDisk(radio){
|
||||
@@ -124,11 +121,11 @@ async function postInit(confirmed, durableId){
|
||||
|
||||
// stepper renders the 3-step progress (Formázás → Csatolás → Regisztrálás) for the running phase.
|
||||
function stepper(phase){
|
||||
var steps=['Formázás','Csatolás','Regisztrálás'];
|
||||
var steps=['{{T "storage_init.formazas"}}','{{T "storage_init.csatolas"}}','{{T "storage_init.regisztralas"}}'];
|
||||
var order={formatting:0,mounting:1,registering:2};
|
||||
var cur=order[phase]!=null?order[phase]:0;
|
||||
var rows=steps.map(function(lbl,i){
|
||||
var state=i<cur?'kész':(i===cur?'folyamatban…':'vár');
|
||||
var state=i<cur?'{{T "storage_init.kesz"}}':(i===cur?'{{T "storage_init.folyamatban"}}':'{{T "storage_init.var"}}');
|
||||
var style=i<cur?'color:var(--accent-ok,#3a9a4a)':(i===cur?'font-weight:600':'opacity:.5');
|
||||
return '<div style="'+style+'">'+(i+1)+'. '+esc(lbl)+' — '+state+'</div>';
|
||||
});
|
||||
@@ -144,18 +141,18 @@ async function pollInitStatus(out, btn){
|
||||
await sleep(1000);
|
||||
var r; try{ r=await fetch('/api/storage/init/status'); }catch(e){ continue; }
|
||||
var j; try{ j=await r.json(); }catch(e){ continue; }
|
||||
if(!j.ok){ out.innerHTML='<div class="alert alert-error">Az állapot lekérdezése sikertelen.</div>'; btn.disabled=false; return; }
|
||||
if(!j.ok){ out.innerHTML='<div class="alert alert-error">{{T "storage_init.az_allapot_lekerdezese_sikertelen"}}</div>'; btn.disabled=false; return; }
|
||||
var d=j.data||{}; var ph=d.phase;
|
||||
if(ph==='formatting'||ph==='mounting'||ph==='registering'){ out.innerHTML=stepper(ph); continue; }
|
||||
if(ph==='idle'){ continue; } // slot not yet populated
|
||||
if(ph==='needs_confirmation'){ renderConfirm(d.durable_id, out, btn); return; }
|
||||
if(ph==='refused'){
|
||||
out.innerHTML='<div class="alert alert-warning"><strong>Operátori aláírás szükséges.</strong> Ez a meghajtó védett (rendszer/biztonsági mentés).'
|
||||
out.innerHTML='<div class="alert alert-warning">{{T "storage_init.operatori_alairas_szukseges_ez_a"}}'
|
||||
+(d.opsign?('<pre class="mono" style="white-space:pre-wrap;background:var(--bg-0);padding:.75rem;border-radius:6px;margin-top:.5rem">'+esc(d.opsign)+'</pre>'):'')+'</div>';
|
||||
btn.disabled=false; return;
|
||||
}
|
||||
if(ph==='done'){ finishInit(d.where, out); return; }
|
||||
if(ph==='failed'){ out.innerHTML='<div class="alert alert-error">Hiba: '+esc(d.error||'')+'</div>'; btn.disabled=false; return; }
|
||||
if(ph==='failed'){ out.innerHTML='<div class="alert alert-error">{{T "storage_init.hiba_2"}} '+esc(d.error||'')+'</div>'; btn.disabled=false; return; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,34 +162,34 @@ async function submitInit(ev){
|
||||
btn.disabled=true; out.innerHTML=stepper('formatting');
|
||||
try{
|
||||
var res=await postInit(false, "");
|
||||
if(res.status===409){ out.innerHTML='<div class="alert alert-warning">'+esc((res.j&&res.j.error)||'Már folyamatban van egy inicializálás.')+'</div>'; btn.disabled=false; return false; }
|
||||
if(!res.j.ok){ out.innerHTML='<div class="alert alert-error">Hiba: '+esc(res.j.error||'')+'</div>'; btn.disabled=false; return false; }
|
||||
if(res.status===409){ out.innerHTML='<div class="alert alert-warning">'+esc((res.j&&res.j.error)||'{{T "storage_init.mar_folyamatban_van_egy_inicializalas"}}')+'</div>'; btn.disabled=false; return false; }
|
||||
if(!res.j.ok){ out.innerHTML='<div class="alert alert-error">{{T "storage_init.hiba_2"}} '+esc(res.j.error||'')+'</div>'; btn.disabled=false; return false; }
|
||||
await pollInitStatus(out, btn);
|
||||
}catch(e){ out.innerHTML='<div class="alert alert-error">Hiba: '+esc(e.message)+'</div>'; btn.disabled=false; }
|
||||
}catch(e){ out.innerHTML='<div class="alert alert-error">{{T "storage_init.hiba_2"}} '+esc(e.message)+'</div>'; btn.disabled=false; }
|
||||
return false;
|
||||
}
|
||||
|
||||
function renderConfirm(durableId, out, btn){
|
||||
var name=document.getElementById('mount-name').value;
|
||||
out.innerHTML='<div class="alert alert-warning">A meghajtó adatot tartalmaz. A formázás <strong>véglegesen törli</strong> a rajta lévő összes adatot.</div>'
|
||||
+'<div class="confirm-input"><label>Megerősítéshez írja be a csatlakoztatási nevet: <strong class="mono">'+esc(name)+'</strong></label>'
|
||||
out.innerHTML='<div class="alert alert-warning">{{T "storage_init.a_meghajto_adatot_tartalmaz_a"}}</div>'
|
||||
+'<div class="confirm-input"><label>{{T "storage_init.megerositeshez_irja_be_a_csatlakoztatasi"}} <strong class="mono">'+esc(name)+'</strong></label>'
|
||||
+'<input type="text" id="init-confirm-type" class="form-control" autocomplete="off" oninput="document.getElementById(\'init-confirm-go\').disabled=(this.value!==\''+esc(name)+'\')"></div>'
|
||||
+'<div class="form-actions" style="gap:.6rem;margin-top:.75rem"><button id="init-confirm-go" class="btn btn-danger-outline" disabled>Törlés és inicializálás megerősítése</button></div>'
|
||||
+'<div class="form-actions" style="gap:.6rem;margin-top:.75rem"><button id="init-confirm-go" class="btn btn-danger-outline" disabled>{{T "storage_init.torles_es_inicializalas_megerositese"}}</button></div>'
|
||||
+'<div id="init-confirm-result" style="margin-top:.6rem"></div>';
|
||||
document.getElementById('init-confirm-go').onclick=async function(){
|
||||
var cr=document.getElementById('init-confirm-result'); cr.innerHTML='<p class="form-hint">Törlés és inicializálás indítása…</p>';
|
||||
var cr=document.getElementById('init-confirm-result'); cr.innerHTML='<p class="form-hint">{{T "storage_init.torles_es_inicializalas_inditasa"}}</p>';
|
||||
try{
|
||||
var res2=await postInit(true, durableId);
|
||||
if(res2.status===409){ cr.innerHTML='<div class="alert alert-warning">'+esc((res2.j&&res2.j.error)||'')+'</div>'; return; }
|
||||
if(!res2.j.ok){ cr.innerHTML='<div class="alert alert-error">Hiba: '+esc(res2.j.error||'')+'</div>'; return; }
|
||||
if(!res2.j.ok){ cr.innerHTML='<div class="alert alert-error">{{T "storage_init.hiba_2"}} '+esc(res2.j.error||'')+'</div>'; return; }
|
||||
out.innerHTML=stepper('formatting');
|
||||
await pollInitStatus(out, btn);
|
||||
}catch(e){ cr.innerHTML='<div class="alert alert-error">Hiba: '+esc(e.message)+'</div>'; }
|
||||
}catch(e){ cr.innerHTML='<div class="alert alert-error">{{T "storage_init.hiba_2"}} '+esc(e.message)+'</div>'; }
|
||||
};
|
||||
}
|
||||
|
||||
function finishInit(where, out){
|
||||
out.innerHTML='<div class="alert alert-success">A meghajtó sikeresen inicializálva és regisztrálva: <strong class="mono">'+esc(where)+'</strong>. <a href="/storage">Vissza a tárhelyhez →</a></div>';
|
||||
out.innerHTML='<div class="alert alert-success">{{T "storage_init.a_meghajto_sikeresen_inicializalva_es"}} <strong class="mono">'+esc(where)+'</strong>{{T "storage_init.vissza_a_tarhelyhez"}}</div>';
|
||||
}
|
||||
loadDisks();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user