diff --git a/android/build.gradle.kts b/android/build.gradle.kts
index ee4a899..a4cd58a 100644
--- a/android/build.gradle.kts
+++ b/android/build.gradle.kts
@@ -1,5 +1,5 @@
plugins {
- id("com.android.application") version "8.3.2" apply false
+ id("com.android.application") version "8.13.2" apply false
id("org.jetbrains.kotlin.android") version "2.0.0" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" apply false
id("org.jetbrains.kotlin.plugin.serialization") version "2.0.0" apply false
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index a80b22c..37f853b 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/web/themes/default/app.js b/web/themes/default/app.js
index 6723a6c..41329dd 100644
--- a/web/themes/default/app.js
+++ b/web/themes/default/app.js
@@ -392,6 +392,16 @@ function applyLang(){
setText('file-ready-btn',T.file_ready_btn);
setText('file-slots-btn',T.file_slots_btn);
setText('file-cancel-btn',T.file_cancel_btn);
+ // Elements not yet covered by setText above
+ var settingsBtn=document.getElementById('settings-btn');
+ if(settingsBtn)settingsBtn.title=T.settings_btn_tooltip||T.settings_title||'Einstellungen';
+ var snpEl=document.getElementById('s-printer-name');
+ if(snpEl)snpEl.placeholder=T.settings_printer_name_placeholder||'z.B. Kobra X Links';
+ var sdidEl=document.getElementById('s-device-id');
+ if(sdidEl)sdidEl.placeholder=T.settings_device_id_placeholder||'32 Hex-Zeichen';
+ setText('d-fan-off',T.label_off||'Aus');
+ setText('skip-confirm',T.skip_confirm_btn||'Überspringen');
+ setText('ams-no-data',T.ams_no_data||'Keine AMS-Daten empfangen');
// GCode-Browser-Karten: Texte sind via innerHTML eingebacken,
// bei Sprachwechsel komplett neu rendern.
if(typeof renderStore==='function' && typeof storeFiles!=='undefined'){
@@ -1029,7 +1039,7 @@ function refreshUserProfileList(){
return '
'
+'★ '+label+''
+''
+ +'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="'+tr('btn_delete','Löschen')+'">🗑'
+'
';
}).join('');
}).catch(function(){});
@@ -1066,7 +1076,7 @@ function refreshImportDialogList(){
return ''
+'★ '+label+''
+''
+ +'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="'+tr('btn_delete','Löschen')+'">🗑'
+'
';
}).join('');
}).catch(function(){});
@@ -1103,7 +1113,7 @@ function doProfileImportUpload(files){
_one(idx+1);
})
.catch(function(e){
- status.textContent='Fehler: '+e;
+ status.textContent=tr('log_error','Fehler:')+' '+e;
status.style.color='var(--err)';
});
}
@@ -1245,7 +1255,7 @@ function startReadyFile(){
if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);}
})
.catch(function(e){
- clog(tr('log_error')+' '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);}
});
}
@@ -1330,7 +1340,7 @@ function saveSlotEdit(){
if(typeof applyState==='function') applyState();
if(typeof poll==='function') poll();
})
- .catch(function(e){clog('Fehler: '+e,'msg-err');});
+ .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err');});
}
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('s-printer-ip').addEventListener('input',function(){
@@ -1377,7 +1387,7 @@ function saveSettings(){
},4000);
}).catch(function(e){
btn.disabled=false;setText('btn-save-settings',T.settings_save);
- clog('Settings-Fehler: '+e,'msg-err');
+ clog(T.settings_title+' '+tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
function checkUpdate(){
@@ -1450,8 +1460,8 @@ var pollTimer;
// ── Print actions ──
function printAction(a){
- post('/printer/print/'+a,{}).then(function(){clog('Druck: '+a,'msg-ok');poll()})
- .catch(function(e){clog('Fehler: '+e,'msg-err')});
+ post('/printer/print/'+a,{}).then(function(){clog(tr('log_print_action','Druck:')+' '+a,'msg-ok');poll()})
+ .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function togglePauseResume(){
// Druckt → pause; Pausiert → resume. Status kommt aus dem zuletzt gepollten
@@ -1490,50 +1500,50 @@ function move(axis,dir,dist){
// axis: 0=X,1=Y,2=Z → printer axis codes: 1=X,2=Y,3=Z
var axisMap={0:1,1:2,2:3};
post('/api/axis',{axis:axisMap[axis],move_type:1,distance:dir*dist})
- .then(function(){clog('Achse '+(axis===0?'X':axis===1?'Y':'Z')+' '+(dir>0?'+':'')+dir*dist+'mm','msg-ok')})
- .catch(function(e){clog('Achse-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_axis','Achse')+' '+(axis===0?'X':axis===1?'Y':'Z')+' '+(dir>0?'+':'')+dir*dist+'mm','msg-ok')})
+ .catch(function(e){clog(tr('log_axis','Achse')+'-'+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function homeAll(){
post('/api/axis',{axis:5,move_type:2,distance:0})
- .then(function(){clog('Home All','msg-ok')})
- .catch(function(e){clog('Home-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_home_all','Home All'),'msg-ok')})
+ .catch(function(e){clog(tr('log_home_all','Home All')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function homeXY(){
post('/api/axis',{axis:4,move_type:2,distance:0})
- .then(function(){clog('Home XY','msg-ok')})
- .catch(function(e){clog('Home-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('btn_home_xy','Home XY'),'msg-ok')})
+ .catch(function(e){clog(tr('btn_home_xy','Home XY')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function homeZ(){
post('/api/axis',{axis:3,move_type:2,distance:0})
- .then(function(){clog('Home Z','msg-ok')})
- .catch(function(e){clog('Home-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('btn_home_z','Home Z'),'msg-ok')})
+ .catch(function(e){clog(tr('btn_home_z','Home Z')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function disableMotors(){
post('/api/axis',{action:'turnOff'})
- .then(function(){clog('Motors Off','msg-ok')})
- .catch(function(e){clog('Motors-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('btn_disable_motors','Motors Off'),'msg-ok')})
+ .catch(function(e){clog(tr('btn_disable_motors','Motors Off')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
// ── Temperature ──
function setNozzle(){
var v=parseFloat(document.getElementById('p-nozzle-inp').value||0);
post('/api/temperature',{nozzle:v,bed:S.bed_target})
- .then(function(){clog('Nozzle → '+v+'°C','msg-ok')})
- .catch(function(e){clog('Temp-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_nozzle','Nozzle → ')+v+'°C','msg-ok')})
+ .catch(function(e){clog(tr('label_nozzle','Düse')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function setBed(){
var v=parseFloat(document.getElementById('p-bed-inp').value||0);
post('/api/temperature',{nozzle:S.nozzle_target,bed:v})
- .then(function(){clog(T.label_bed+' → '+v+'°C','msg-ok')})
- .catch(function(e){clog('Temp-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_bed','Bett → ')+v+'°C','msg-ok')})
+ .catch(function(e){clog(tr('label_bed','Bett')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
// ── Light ──
function setLight(){
var on=document.getElementById('d-light-toggle').checked;
post('/api/light',{on:on,brightness:80})
- .then(function(){clog('Licht '+(on?'an, '+br+'%':'aus'),'msg-ok')})
- .catch(function(e){clog('Licht-Fehler: '+e,'msg-err')});
+ .then(function(){clog(on?tr('log_light_on','Licht an'):tr('log_light_off','Licht aus'),'msg-ok')})
+ .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')});
}
// ── Print Speed ──
@@ -1544,7 +1554,7 @@ function setSpeed(mode){
if(b) b.classList.toggle('spd-active',m===mode);
});
post('/api/speed',{mode:mode})
- .catch(function(e){clog('Speed-Fehler: '+e,'msg-err')});
+ .catch(function(e){clog(tr('label_speed','Geschwindigkeit')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
// ── Fan ──
@@ -1552,15 +1562,15 @@ function setFan(){
var v=parseInt(document.getElementById('d-fan').value);
document.getElementById('d-fan-val').textContent=v;
post('/api/fan',{speed:v})
- .then(function(){clog('Lüfter → '+v+'%','msg-ok')})
- .catch(function(e){clog('Lüfter-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_fan','Lüfter → ')+v+'%','msg-ok')})
+ .catch(function(e){clog(tr('log_fan','Lüfter → ')+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function quickFan(v){
document.getElementById('d-fan').value=v;
document.getElementById('d-fan-val').textContent=v;
post('/api/fan',{speed:v})
- .then(function(){clog('Lüfter → '+v+'%','msg-ok')})
- .catch(function(e){clog('Lüfter-Fehler: '+e,'msg-err')});
+ .then(function(){clog(tr('log_fan','Lüfter → ')+v+'%','msg-ok')})
+ .catch(function(e){clog(tr('log_fan','Lüfter → ')+tr('log_error','Fehler:')+' '+e,'msg-err')});
}
// ── AMS ──
@@ -1575,7 +1585,7 @@ function amsFeed(type,slotIndex){
}
return post('/api/ams/feed',{slot_index:globalIdx,type:type})
.then(function(){clog((type===1?T.lbl_feed:T.lbl_unload)+' Slot '+(globalIdx+1),'msg-ok')})
- .catch(function(e){clog('AMS-Fehler: '+e,'msg-err');throw e;});
+ .catch(function(e){clog('AMS '+tr('log_error','Fehler:')+' '+e,'msg-err');throw e;});
}
// ── Camera ──
@@ -1593,7 +1603,7 @@ function camStart(){
ph.style.display='flex';
camOn=false;
document.getElementById('cam-toggle-btn').textContent=tr('btn_cam_start');
- clog(tr('log_error')+' '+tr('cam_stream_unavailable'),'msg-err');
+ clog(tr('log_error','Fehler:')+' '+tr('cam_stream_unavailable'),'msg-err');
};
img.src='/api/camera/stream?t='+Date.now();
camOn=true;
@@ -1607,7 +1617,7 @@ function camStart(){
}).catch(function(e){
sp.style.display='none';
ph.style.display='flex';
- clog(tr('log_error')+' '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
@@ -1636,7 +1646,7 @@ function aceDryStart(aceId){
clog('ACE '+(aceId+1)+' - '+tr('ace_dry_dryer')+': '+tr('ace_dry_start')+' ('+t+'°C, '+d+' min)','msg-ok');
poll();
})
- .catch(function(e){clog('ACE-Fehler: '+e,'msg-err');});
+ .catch(function(e){clog('ACE '+tr('log_error','Fehler:')+' '+e,'msg-err');});
}
var _aceAutoFeedPending={};
@@ -1840,7 +1850,7 @@ function saveAceDryPresetAndRestart(){
}).catch(function(e){
btn.disabled=false;
btn.textContent=tr('ace_dry_dialog_save_restart');
- clog('ACE-Preset Fehler: '+e,'msg-err');
+ clog('ACE preset '+tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
@@ -1878,14 +1888,14 @@ function aceDryStop(aceId){
clog('ACE '+(aceId+1)+' - '+tr('ace_dry_dryer')+': '+tr('ace_dry_stop'),'msg-ok');
poll();
})
- .catch(function(e){clog('ACE-Fehler: '+e,'msg-err');});
+ .catch(function(e){clog('ACE '+tr('log_error','Fehler:')+' '+e,'msg-err');});
}
function loadStore(){
fetch(_apiUrl('/kx/files')).then(function(r){return r.json()}).then(function(d){
storeFiles=d.result||[];
renderStore();
- }).catch(function(e){clog('Store-Fehler: '+e,'msg-err')});
+ }).catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')});
}
function uploadGcode(file){
@@ -1917,7 +1927,7 @@ function uploadGcode(file){
if(status){ status.textContent=T.store_upload_error.replace('{error}',e.message); status.className='upload-status-err'; }
if(label) label.style.display='';
if(zone) zone.style.pointerEvents='';
- clog('Upload-Fehler: '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
@@ -2074,7 +2084,7 @@ function clearWebUploadWarningFlag(fileId, onDone){
loadStore();
})
.catch(function(e){
- clog('Verifizierungs-Fehler: '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
@@ -2140,7 +2150,7 @@ function confirmStoreWebVerify(){
})
.catch(function(e){
if(status){status.textContent='✗ '+e.message;}
- clog('Verifizierungs-Fehler: '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
});
}
@@ -2387,7 +2397,7 @@ function confirmFilamentPrint(){
if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);}
})
.catch(function(e){
- clog(tr('log_error')+' '+e,'msg-err');
+ clog(tr('log_error','Fehler:')+' '+e,'msg-err');
if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);}
});
} else {
@@ -2397,9 +2407,9 @@ function confirmFilamentPrint(){
headers:{'Content-Type':'application/json'},
body:JSON.stringify({file_id:_storeFileId,filament_assignments:assignments,excluded_objects:excludedObjects})
}).then(function(r){return r.json()}).then(function(d){
- if(d.result==='ok'){clog('Druckstart: '+_storeFilename,'msg-ok');showPanel('dashboard');}
- else{clog('Druckfehler: '+(d.error||'?'),'msg-err');}
- }).catch(function(e){clog('Druckfehler: '+e,'msg-err');});
+ if(d.result==='ok'){clog(tr('log_print_start','Druckstart:')+' '+_storeFilename,'msg-ok');showPanel('dashboard');}
+ else{clog(tr('log_error','Fehler:')+' '+(d.error||'?'),'msg-err');}
+ }).catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err');});
}
}
@@ -2553,7 +2563,7 @@ function confirmSkip(){
fetch(_apiUrl('/kx/skip'),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({names:names})})
.then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});})
.then(function(res){
- if(!res.ok){st.textContent=(res.j&&res.j.error)||'Fehler';st.style.color='var(--err)';btn.disabled=false;return;}
+ if(!res.ok){st.textContent=(res.j&&res.j.error)||tr('log_error','Fehler:');st.style.color='var(--err)';btn.disabled=false;return;}
st.textContent=tr('skip_success');st.style.color='var(--ok)';
// Dialog offen lassen + neu laden damit der "übersprungen"-Status erscheint
setTimeout(function(){ _refreshSkipDialog(); btn.disabled=false; st.textContent=''; }, 1500);
@@ -2565,7 +2575,7 @@ function storeDelete(fileId){
if(!confirm(T.store_delete_confirm)) return;
fetch(_apiUrl('/kx/files/'+fileId),{method:'DELETE'}).then(function(r){
if(r.ok){loadStore();}
- else{clog('Löschen fehlgeschlagen','msg-err');}
+ else{clog(tr('log_delete_failed','Löschen fehlgeschlagen'),'msg-err');}
});
}
@@ -2599,7 +2609,7 @@ function confirmAddPrinter(){
body:JSON.stringify({printer_ip:ip,name:name})})
.then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});})
.then(function(res){
- if(!res.ok){st.textContent=(res.j&&res.j.error)||'Fehler';st.style.color='var(--err)';btn.disabled=false;return;}
+ if(!res.ok){st.textContent=(res.j&&res.j.error)||tr('log_error','Fehler:');st.style.color='var(--err)';btn.disabled=false;return;}
st.textContent=T.apd_success;st.style.color='var(--ok)';
setTimeout(function(){location.reload();},2500);
})
@@ -2610,7 +2620,7 @@ function removePrinter(id,name){
fetch('/kx/printers/'+encodeURIComponent(id),{method:'DELETE'})
.then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});})
.then(function(res){
- if(!res.ok){alert((res.j&&res.j.error)||'Fehler');return;}
+ if(!res.ok){alert((res.j&&res.j.error)||tr('log_error','Fehler:'));return;}
setTimeout(function(){location.href='/printer1';},2000);
})
.catch(function(e){alert(''+e);});
@@ -2679,6 +2689,6 @@ function loadPrinterTab(){
}).join('');
});
}).catch(function(e){
- if(grid)grid.innerHTML='Fehler: '+e+'
';
+ if(grid)grid.innerHTML=''+tr('log_error','Fehler:')+' '+e+'
';
});
}
diff --git a/web/themes/default/index.html b/web/themes/default/index.html
index 1c3c2ed..59d6ea1 100644
--- a/web/themes/default/index.html
+++ b/web/themes/default/index.html
@@ -424,7 +424,7 @@
0
-
+
diff --git a/web/translations/de.json b/web/translations/de.json
index 6e6fac1..8573e4a 100644
--- a/web/translations/de.json
+++ b/web/translations/de.json
@@ -261,5 +261,13 @@
"settings_notif_min_unit": "Min.",
"settings_notif_layers_unit": "Layer",
"settings_notif_zero_off": "(0 = aus)",
- "settings_notif_send_image": "Bild"
+ "settings_notif_send_image": "Bild",
+ "settings_btn_tooltip": "Einstellungen",
+ "settings_printer_name_placeholder": "z.B. Kobra X Links",
+ "settings_device_id_placeholder": "32 Hex-Zeichen",
+ "skip_confirm_btn": "Überspringen",
+ "btn_delete": "Löschen",
+ "log_print_start": "Druckstart:",
+ "log_print_action": "Druck:",
+ "log_delete_failed": "Löschen fehlgeschlagen"
}
diff --git a/web/translations/en.json b/web/translations/en.json
index decf3ea..7ca5e39 100644
--- a/web/translations/en.json
+++ b/web/translations/en.json
@@ -261,5 +261,13 @@
"settings_notif_min_unit": "min",
"settings_notif_layers_unit": "layers",
"settings_notif_zero_off": "(0 = off)",
- "settings_notif_send_image": "Image"
+ "settings_notif_send_image": "Image",
+ "settings_btn_tooltip": "Settings",
+ "settings_printer_name_placeholder": "e.g. Kobra X Left",
+ "settings_device_id_placeholder": "32 hex characters",
+ "skip_confirm_btn": "Skip",
+ "btn_delete": "Delete",
+ "log_print_start": "Print start:",
+ "log_print_action": "Print:",
+ "log_delete_failed": "Delete failed"
}
diff --git a/web/translations/es.json b/web/translations/es.json
index b6177b1..04b6416 100644
--- a/web/translations/es.json
+++ b/web/translations/es.json
@@ -261,5 +261,13 @@
"settings_notif_min_unit": "min",
"settings_notif_layers_unit": "capas",
"settings_notif_zero_off": "(0 = off)",
- "settings_notif_send_image": "Imagen"
+ "settings_notif_send_image": "Imagen",
+ "settings_btn_tooltip": "Configuración",
+ "settings_printer_name_placeholder": "p. ej. Kobra X Izquierda",
+ "settings_device_id_placeholder": "32 caracteres hexadecimales",
+ "skip_confirm_btn": "Omitir",
+ "btn_delete": "Eliminar",
+ "log_print_start": "Inicio de impresión:",
+ "log_print_action": "Imprimir:",
+ "log_delete_failed": "Error al eliminar"
}
diff --git a/web/translations/zh-cn.json b/web/translations/zh-cn.json
index e0a7f80..935041b 100644
--- a/web/translations/zh-cn.json
+++ b/web/translations/zh-cn.json
@@ -261,5 +261,13 @@
"settings_notif_min_unit": "分钟",
"settings_notif_layers_unit": "层",
"settings_notif_zero_off": "(0 = 关闭)",
- "settings_notif_send_image": "图片"
+ "settings_notif_send_image": "图片",
+ "settings_btn_tooltip": "设置",
+ "settings_printer_name_placeholder": "例如 Kobra X 左侧",
+ "settings_device_id_placeholder": "32位十六进制字符",
+ "skip_confirm_btn": "跳过",
+ "btn_delete": "删除",
+ "log_print_start": "开始打印:",
+ "log_print_action": "打印:",
+ "log_delete_failed": "删除失败"
}