fix: align German online backup controls
Use compact German key labels and a shared fixed label column so both online-backup inputs and actions align consistently across languages. Restore the narrow one-column breakpoint after later settings overrides and cover translations plus real hidden CSS geometry.
This commit is contained in:
+2
-2
@@ -4872,12 +4872,12 @@ function renderSettings() {
|
|||||||
<span class="hint">Jeder Export erzeugt einen neuen Schlüssel. Ältere Schlüssel bleiben gültig.</span>
|
<span class="hint">Jeder Export erzeugt einen neuen Schlüssel. Ältere Schlüssel bleiben gültig.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="online-backup-key-row">
|
<div class="online-backup-key-row">
|
||||||
<label for="onlineBackupKeyOutput">Dein neuer Schlüssel</label>
|
<label for="onlineBackupKeyOutput">Neuer Schlüssel</label>
|
||||||
<input type="text" class="key-input" id="onlineBackupKeyOutput" readonly spellcheck="false" autocomplete="off" placeholder="Nach dem Export erscheint hier der 75-stellige Schlüssel">
|
<input type="text" class="key-input" id="onlineBackupKeyOutput" readonly spellcheck="false" autocomplete="off" placeholder="Nach dem Export erscheint hier der 75-stellige Schlüssel">
|
||||||
<button class="btn btn-secondary" id="copyOnlineBackupKeyBtn" disabled>Kopieren</button>
|
<button class="btn btn-secondary" id="copyOnlineBackupKeyBtn" disabled>Kopieren</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="online-backup-key-row">
|
<div class="online-backup-key-row">
|
||||||
<label for="onlineBackupKeyInput">Vorhandenen Schlüssel importieren</label>
|
<label for="onlineBackupKeyInput">Schlüssel importieren</label>
|
||||||
<input type="password" class="key-input" id="onlineBackupKeyInput" maxlength="75" pattern="MHU2-[A-Za-z0-9_-]{70}" spellcheck="false" autocomplete="off" placeholder="MHU2-…">
|
<input type="password" class="key-input" id="onlineBackupKeyInput" maxlength="75" pattern="MHU2-[A-Za-z0-9_-]{70}" spellcheck="false" autocomplete="off" placeholder="MHU2-…">
|
||||||
<button class="btn btn-secondary" id="restoreOnlineBackupBtn" disabled>Online importieren</button>
|
<button class="btn btn-secondary" id="restoreOnlineBackupBtn" disabled>Online importieren</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -309,7 +309,9 @@
|
|||||||
['Neuen Schlüssel erzeugen', 'Generate new key'],
|
['Neuen Schlüssel erzeugen', 'Generate new key'],
|
||||||
['Jeder Export erzeugt einen neuen Schlüssel. Ältere Schlüssel bleiben gültig.', 'Each export creates a new key. Older keys remain valid.'],
|
['Jeder Export erzeugt einen neuen Schlüssel. Ältere Schlüssel bleiben gültig.', 'Each export creates a new key. Older keys remain valid.'],
|
||||||
['Dein neuer Schlüssel', 'Your new key'],
|
['Dein neuer Schlüssel', 'Your new key'],
|
||||||
|
['Neuer Schlüssel', 'Your new key'],
|
||||||
['Vorhandenen Schlüssel importieren', 'Import existing key'],
|
['Vorhandenen Schlüssel importieren', 'Import existing key'],
|
||||||
|
['Schlüssel importieren', 'Import existing key'],
|
||||||
['Online importieren', 'Import online'],
|
['Online importieren', 'Import online'],
|
||||||
['Behandle den Schlüssel wie ein Passwort. Wer ihn besitzt, kann die verschlüsselten Einstellungen entschlüsseln.', 'Treat the key like a password. Anyone who has it can decrypt the encrypted settings.'],
|
['Behandle den Schlüssel wie ein Passwort. Wer ihn besitzt, kann die verschlüsselten Einstellungen entschlüsseln.', 'Treat the key like a password. Anyone who has it can decrypt the encrypted settings.'],
|
||||||
['Lokales Datei-Backup', 'Local file backup'],
|
['Lokales Datei-Backup', 'Local file backup'],
|
||||||
|
|||||||
+8
-2
@@ -1896,7 +1896,7 @@ select.hs-input { max-width: none; width: auto; min-width: 140px; }
|
|||||||
|
|
||||||
.online-backup-key-row {
|
.online-backup-key-row {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(170px, auto) minmax(240px, 1fr) auto;
|
grid-template-columns: 150px minmax(240px, 1fr) auto;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
@@ -3603,7 +3603,13 @@ input[type="checkbox"] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.online-backup-key-row {
|
.online-backup-key-row {
|
||||||
grid-template-columns: minmax(140px, auto) minmax(180px, 1fr) auto;
|
grid-template-columns: 150px minmax(180px, 1fr) auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 820px) {
|
||||||
|
.online-backup-key-row {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#settings-view {
|
#settings-view {
|
||||||
|
|||||||
@@ -16,6 +16,13 @@ test('translates the remaining upload size label', () => {
|
|||||||
assert.equal(translateText('Remaining size', 'de'), 'Verbleibende Größe');
|
assert.equal(translateText('Remaining size', 'de'), 'Verbleibende Größe');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('translates compact online backup labels in both directions', () => {
|
||||||
|
assert.equal(translateText('Neuer Schlüssel', 'en'), 'Your new key');
|
||||||
|
assert.equal(translateText('Your new key', 'de'), 'Neuer Schlüssel');
|
||||||
|
assert.equal(translateText('Schlüssel importieren', 'en'), 'Import existing key');
|
||||||
|
assert.equal(translateText('Import existing key', 'de'), 'Schlüssel importieren');
|
||||||
|
});
|
||||||
|
|
||||||
test('translates the account check timestamp label', () => {
|
test('translates the account check timestamp label', () => {
|
||||||
assert.equal(translateText('geprüft', 'en'), 'checked');
|
assert.equal(translateText('geprüft', 'en'), 'checked');
|
||||||
assert.equal(translateText('checked', 'de'), 'geprüft');
|
assert.equal(translateText('checked', 'de'), 'geprüft');
|
||||||
|
|||||||
@@ -69,6 +69,17 @@ contextBridge.exposeInMainWorld('api', {
|
|||||||
getConfig() { return new Promise(() => {}); }
|
getConfig() { return new Promise(() => {}); }
|
||||||
});
|
});
|
||||||
`, 'utf8');
|
`, 'utf8');
|
||||||
|
const onlineBackupLayoutScript = `(() => {
|
||||||
|
document.documentElement.lang = 'de';
|
||||||
|
document.body.innerHTML = '<section class="online-backup-panel"><div class="online-backup-key-row"><label>Dein neuer Schlüssel</label><input class="key-input"><button class="btn btn-secondary">Kopieren</button></div><div class="online-backup-key-row"><label>Vorhandenen Schlüssel importieren</label><input class="key-input"><button class="btn btn-secondary">Online importieren</button></div></section>';
|
||||||
|
const rows = [...document.querySelectorAll('.online-backup-key-row')];
|
||||||
|
return rows.map(row => {
|
||||||
|
const label = row.querySelector('label').getBoundingClientRect();
|
||||||
|
const input = row.querySelector('input').getBoundingClientRect();
|
||||||
|
const button = row.querySelector('button').getBoundingClientRect();
|
||||||
|
return { labelWidth: label.width, inputLeft: input.left, buttonRight: button.right };
|
||||||
|
});
|
||||||
|
})()`;
|
||||||
const probeSource = `
|
const probeSource = `
|
||||||
const { app, BrowserWindow, screen } = require('electron');
|
const { app, BrowserWindow, screen } = require('electron');
|
||||||
const { execFileSync } = require('node:child_process');
|
const { execFileSync } = require('node:child_process');
|
||||||
@@ -104,6 +115,7 @@ app.whenReady().then(async () => {
|
|||||||
const middleY = Math.floor(size.height / 2);
|
const middleY = Math.floor(size.height / 2);
|
||||||
await window.loadFile(process.env.MHU_RENDERER_PATH, { query: { language: 'en', version: '2.1.31' } });
|
await window.loadFile(process.env.MHU_RENDERER_PATH, { query: { language: 'en', version: '2.1.31' } });
|
||||||
const liveSpeedChart = await window.webContents.executeJavaScript('({ baselinePresent: Boolean(document.querySelector(".upload-speed-baseline")), canvasWidth: document.getElementById("uploadSpeedCanvas")?.getBoundingClientRect().width || 0 })');
|
const liveSpeedChart = await window.webContents.executeJavaScript('({ baselinePresent: Boolean(document.querySelector(".upload-speed-baseline")), canvasWidth: document.getElementById("uploadSpeedCanvas")?.getBoundingClientRect().width || 0 })');
|
||||||
|
const onlineBackupLayout = await window.webContents.executeJavaScript(${JSON.stringify(onlineBackupLayoutScript)});
|
||||||
fs.writeFileSync(outputPath, JSON.stringify({
|
fs.writeFileSync(outputPath, JSON.stringify({
|
||||||
size,
|
size,
|
||||||
dom,
|
dom,
|
||||||
@@ -114,7 +126,8 @@ app.whenReady().then(async () => {
|
|||||||
rendererCommandLine,
|
rendererCommandLine,
|
||||||
leftEdge: pixelAt(bitmap, size.width, 0, middleY),
|
leftEdge: pixelAt(bitmap, size.width, 0, middleY),
|
||||||
rightEdge: pixelAt(bitmap, size.width, size.width - 1, middleY),
|
rightEdge: pixelAt(bitmap, size.width, size.width - 1, middleY),
|
||||||
liveSpeedChart
|
liveSpeedChart,
|
||||||
|
onlineBackupLayout
|
||||||
}), 'utf8');
|
}), 'utf8');
|
||||||
window.destroy();
|
window.destroy();
|
||||||
app.exit(0);
|
app.exit(0);
|
||||||
@@ -154,6 +167,10 @@ app.whenReady().then(async () => {
|
|||||||
assert.ok(result.rightEdge[0] > result.rightEdge[1] && result.rightEdge[2] > result.rightEdge[1]);
|
assert.ok(result.rightEdge[0] > result.rightEdge[1] && result.rightEdge[2] > result.rightEdge[1]);
|
||||||
assert.ok(result.liveSpeedChart.canvasWidth > 0);
|
assert.ok(result.liveSpeedChart.canvasWidth > 0);
|
||||||
assert.equal(result.liveSpeedChart.baselinePresent, false);
|
assert.equal(result.liveSpeedChart.baselinePresent, false);
|
||||||
|
assert.equal(result.onlineBackupLayout.length, 2);
|
||||||
|
assert.ok(Math.abs(result.onlineBackupLayout[0].labelWidth - result.onlineBackupLayout[1].labelWidth) <= 1);
|
||||||
|
assert.ok(Math.abs(result.onlineBackupLayout[0].inputLeft - result.onlineBackupLayout[1].inputLeft) <= 1);
|
||||||
|
assert.ok(Math.abs(result.onlineBackupLayout[0].buttonRight - result.onlineBackupLayout[1].buttonRight) <= 1);
|
||||||
} finally {
|
} finally {
|
||||||
fs.rmSync(probeRoot, { recursive: true, force: true });
|
fs.rmSync(probeRoot, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user