Separate strings.js file
All checks were successful
Build and test project / build-and-test (push) Successful in 1m53s
All checks were successful
Build and test project / build-and-test (push) Successful in 1m53s
This commit is contained in:
@@ -10,9 +10,14 @@ const srcDir = join(webDir, 'src');
|
|||||||
const distDir = join(webDir, 'dist');
|
const distDir = join(webDir, 'dist');
|
||||||
const isDev = process.argv.includes('--dev');
|
const isDev = process.argv.includes('--dev');
|
||||||
|
|
||||||
// Clean dist/
|
// Clean dist/ (preserve wasm/ which is built separately)
|
||||||
if (existsSync(distDir)) rmSync(distDir, { recursive: true });
|
if (existsSync(distDir)) {
|
||||||
mkdirSync(distDir, { recursive: true });
|
for (const entry of readdirSync(distDir)) {
|
||||||
|
if (entry !== 'wasm') {
|
||||||
|
rmSync(join(distDir, entry), { recursive: true, force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build JS bundle
|
// Build JS bundle
|
||||||
await esbuild.build({
|
await esbuild.build({
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { loadSoftwareUrls, getSoftwareUrl, getDevicesForVersion } from './kobo-s
|
|||||||
import { PatchUI, scanAvailablePatches } from './patch-ui.js';
|
import { PatchUI, scanAvailablePatches } from './patch-ui.js';
|
||||||
import { KoboPatchRunner } from './patch-runner.js';
|
import { KoboPatchRunner } from './patch-runner.js';
|
||||||
import { NickelMenuInstaller } from './nickelmenu.js';
|
import { NickelMenuInstaller } from './nickelmenu.js';
|
||||||
|
import { TL } from './strings.js';
|
||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
|
|
||||||
(() => {
|
(() => {
|
||||||
@@ -130,11 +131,8 @@ import JSZip from 'jszip';
|
|||||||
];
|
];
|
||||||
|
|
||||||
// --- Step navigation ---
|
// --- Step navigation ---
|
||||||
const NAV_NICKELMENU = ['Device', 'Mode', 'Configure', 'Review', 'Install'];
|
|
||||||
const NAV_PATCHES = ['Device', 'Mode', 'Patches', 'Build', 'Install'];
|
|
||||||
const NAV_DEFAULT = ['Device', 'Mode', 'Patches', 'Build', 'Install'];
|
|
||||||
|
|
||||||
let currentNavLabels = NAV_DEFAULT;
|
let currentNavLabels = TL.NAV_DEFAULT;
|
||||||
|
|
||||||
const stepHistory = [stepConnect];
|
const stepHistory = [stepConnect];
|
||||||
|
|
||||||
@@ -204,9 +202,9 @@ import JSZip from 'jszip';
|
|||||||
const count = patchUI.getEnabledCount();
|
const count = patchUI.getEnabledCount();
|
||||||
btnPatchesNext.disabled = false;
|
btnPatchesNext.disabled = false;
|
||||||
if (count === 0) {
|
if (count === 0) {
|
||||||
patchCountHint.textContent = 'No patches selected \u2014 continuing will restore the original unpatched software.';
|
patchCountHint.textContent = TL.STATUS.PATCH_COUNT_ZERO;
|
||||||
} else {
|
} else {
|
||||||
patchCountHint.textContent = count === 1 ? '1 patch selected.' : count + ' patches selected.';
|
patchCountHint.textContent = count === 1 ? TL.STATUS.PATCH_COUNT_ONE : TL.STATUS.PATCH_COUNT_MULTI(count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +230,7 @@ import JSZip from 'jszip';
|
|||||||
$('connect-unsupported-hint').hidden = false;
|
$('connect-unsupported-hint').hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNavLabels(NAV_DEFAULT);
|
setNavLabels(TL.NAV_DEFAULT);
|
||||||
setNavStep(1);
|
setNavStep(1);
|
||||||
showStep(stepConnect);
|
showStep(stepConnect);
|
||||||
|
|
||||||
@@ -280,7 +278,7 @@ import JSZip from 'jszip';
|
|||||||
try {
|
try {
|
||||||
const loaded = await loadPatchesForVersion(version, availablePatches);
|
const loaded = await loadPatchesForVersion(version, availablePatches);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
showError('Could not load patches for software version ' + version);
|
showError(TL.ERROR.LOAD_PATCHES_FAILED(version));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
configureFirmwareStep(version, selectedPrefix);
|
configureFirmwareStep(version, selectedPrefix);
|
||||||
@@ -345,7 +343,7 @@ import JSZip from 'jszip';
|
|||||||
deviceUnknownCheckbox.checked = false;
|
deviceUnknownCheckbox.checked = false;
|
||||||
btnDeviceNext.disabled = true;
|
btnDeviceNext.disabled = true;
|
||||||
} else {
|
} else {
|
||||||
deviceStatus.textContent = 'Your device has been recognized. You can continue to the next step!';
|
deviceStatus.textContent = TL.STATUS.DEVICE_RECOGNIZED;
|
||||||
deviceUnknownWarning.hidden = true;
|
deviceUnknownWarning.hidden = true;
|
||||||
deviceUnknownAck.hidden = true;
|
deviceUnknownAck.hidden = true;
|
||||||
deviceUnknownCheckbox.checked = false;
|
deviceUnknownCheckbox.checked = false;
|
||||||
@@ -372,7 +370,7 @@ import JSZip from 'jszip';
|
|||||||
if (!patchesLoaded) return;
|
if (!patchesLoaded) return;
|
||||||
selectedMode = 'patches';
|
selectedMode = 'patches';
|
||||||
isRestore = true;
|
isRestore = true;
|
||||||
setNavLabels(NAV_PATCHES);
|
setNavLabels(TL.NAV_PATCHES);
|
||||||
goToBuild();
|
goToBuild();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -410,7 +408,7 @@ import JSZip from 'jszip';
|
|||||||
patchesHint.hidden = true;
|
patchesHint.hidden = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
setNavLabels(NAV_DEFAULT);
|
setNavLabels(TL.NAV_DEFAULT);
|
||||||
setNavStep(2);
|
setNavStep(2);
|
||||||
showStep(stepMode);
|
showStep(stepMode);
|
||||||
}
|
}
|
||||||
@@ -430,14 +428,14 @@ import JSZip from 'jszip';
|
|||||||
selectedMode = selected.value;
|
selectedMode = selected.value;
|
||||||
|
|
||||||
if (selectedMode === 'nickelmenu') {
|
if (selectedMode === 'nickelmenu') {
|
||||||
setNavLabels(NAV_NICKELMENU);
|
setNavLabels(TL.NAV_NICKELMENU);
|
||||||
goToNickelMenuConfig();
|
goToNickelMenuConfig();
|
||||||
} else if (manualMode && !patchesLoaded) {
|
} else if (manualMode && !patchesLoaded) {
|
||||||
// Manual mode: need version/model selection before patches
|
// Manual mode: need version/model selection before patches
|
||||||
setNavLabels(NAV_PATCHES);
|
setNavLabels(TL.NAV_PATCHES);
|
||||||
await enterManualVersionSelection();
|
await enterManualVersionSelection();
|
||||||
} else {
|
} else {
|
||||||
setNavLabels(NAV_PATCHES);
|
setNavLabels(TL.NAV_PATCHES);
|
||||||
goToPatches();
|
goToPatches();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -481,7 +479,7 @@ import JSZip from 'jszip';
|
|||||||
await addsDir.getDirectoryHandle('nm');
|
await addsDir.getDirectoryHandle('nm');
|
||||||
removeRadio.disabled = false;
|
removeRadio.disabled = false;
|
||||||
removeOption.classList.remove('nm-option-disabled');
|
removeOption.classList.remove('nm-option-disabled');
|
||||||
removeDesc.textContent = 'Removes NickelMenu from your device. You must restart your Kobo to complete the uninstall!';
|
removeDesc.textContent = TL.STATUS.NM_REMOVAL_HINT;
|
||||||
return;
|
return;
|
||||||
} catch {
|
} catch {
|
||||||
// .adds/nm not found
|
// .adds/nm not found
|
||||||
@@ -490,7 +488,7 @@ import JSZip from 'jszip';
|
|||||||
|
|
||||||
removeRadio.disabled = true;
|
removeRadio.disabled = true;
|
||||||
removeOption.classList.add('nm-option-disabled');
|
removeOption.classList.add('nm-option-disabled');
|
||||||
removeDesc.textContent = 'Removes NickelMenu from your device. Only available when a Kobo with NickelMenu installed is connected.';
|
removeDesc.textContent = TL.STATUS.NM_REMOVAL_DISABLED;
|
||||||
if (removeRadio.checked) {
|
if (removeRadio.checked) {
|
||||||
const sampleRadio = $q('input[value="sample"]', stepNickelMenu);
|
const sampleRadio = $q('input[value="sample"]', stepNickelMenu);
|
||||||
sampleRadio.checked = true;
|
sampleRadio.checked = true;
|
||||||
@@ -540,33 +538,33 @@ import JSZip from 'jszip';
|
|||||||
list.innerHTML = '';
|
list.innerHTML = '';
|
||||||
|
|
||||||
if (nickelMenuOption === 'remove') {
|
if (nickelMenuOption === 'remove') {
|
||||||
summary.textContent = 'NickelMenu will be updated and marked for removal. It will uninstall itself when your Kobo reboots.';
|
summary.textContent = TL.STATUS.NM_WILL_BE_REMOVED;
|
||||||
btnNmWrite.hidden = manualMode;
|
btnNmWrite.hidden = manualMode;
|
||||||
btnNmWrite.textContent = 'Remove from Kobo';
|
btnNmWrite.textContent = TL.BUTTON.REMOVE_FROM_KOBO;
|
||||||
btnNmDownload.hidden = true;
|
btnNmDownload.hidden = true;
|
||||||
} else if (nickelMenuOption === 'nickelmenu-only') {
|
} else if (nickelMenuOption === 'nickelmenu-only') {
|
||||||
summary.textContent = 'The following will be installed on your Kobo:';
|
summary.textContent = TL.STATUS.NM_WILL_BE_INSTALLED;
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.textContent = 'NickelMenu (KoboRoot.tgz)';
|
li.textContent = TL.STATUS.NM_NICKEL_ROOT_TGZ;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
btnNmWrite.hidden = false;
|
btnNmWrite.hidden = false;
|
||||||
btnNmWrite.textContent = 'Write to Kobo';
|
btnNmWrite.textContent = TL.BUTTON.WRITE_TO_KOBO;
|
||||||
btnNmDownload.hidden = false;
|
btnNmDownload.hidden = false;
|
||||||
} else {
|
} else {
|
||||||
summary.textContent = 'The following will be installed on your Kobo:';
|
summary.textContent = TL.STATUS.NM_WILL_BE_INSTALLED;
|
||||||
const items = ['NickelMenu (KoboRoot.tgz)', 'Custom menu configuration'];
|
const items = [TL.STATUS.NM_NICKEL_ROOT_TGZ, 'Custom menu configuration'];
|
||||||
const cfg = getNmConfig();
|
const cfg = getNmConfig();
|
||||||
if (cfg.fonts) items.push('Readerly fonts');
|
if (cfg.fonts) items.push(TL.NICKEL_MENU_ITEMS.FONTS);
|
||||||
if (cfg.screensaver) items.push('Custom screensaver');
|
if (cfg.screensaver) items.push(TL.NICKEL_MENU_ITEMS.SCREENSAVER);
|
||||||
if (cfg.simplifyTabs) items.push('Simplified tab menu');
|
if (cfg.simplifyTabs) items.push(TL.NICKEL_MENU_ITEMS.SIMPLIFY_TABS);
|
||||||
if (cfg.simplifyHome) items.push('Simplified homescreen');
|
if (cfg.simplifyHome) items.push(TL.NICKEL_MENU_ITEMS.SIMPLIFY_HOME);
|
||||||
for (const text of items) {
|
for (const text of items) {
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
li.textContent = text;
|
li.textContent = text;
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
}
|
}
|
||||||
btnNmWrite.hidden = false;
|
btnNmWrite.hidden = false;
|
||||||
btnNmWrite.textContent = 'Write to Kobo';
|
btnNmWrite.textContent = TL.BUTTON.WRITE_TO_KOBO;
|
||||||
btnNmDownload.hidden = false;
|
btnNmDownload.hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +615,7 @@ import JSZip from 'jszip';
|
|||||||
showNmDone('download');
|
showNmDone('download');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showError('NickelMenu installation failed: ' + err.message);
|
showError(TL.STATUS.NM_INSTALL_FAILED + err.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,13 +629,13 @@ import JSZip from 'jszip';
|
|||||||
$('nm-reboot-instructions').hidden = true;
|
$('nm-reboot-instructions').hidden = true;
|
||||||
|
|
||||||
if (mode === 'remove') {
|
if (mode === 'remove') {
|
||||||
nmDoneStatus.textContent = 'NickelMenu will be removed on next reboot.';
|
nmDoneStatus.textContent = TL.STATUS.NM_REMOVED_ON_REBOOT;
|
||||||
$('nm-reboot-instructions').hidden = false;
|
$('nm-reboot-instructions').hidden = false;
|
||||||
} else if (mode === 'written') {
|
} else if (mode === 'written') {
|
||||||
nmDoneStatus.textContent = 'NickelMenu has been installed on your Kobo.';
|
nmDoneStatus.textContent = TL.STATUS.NM_INSTALLED;
|
||||||
$('nm-write-instructions').hidden = false;
|
$('nm-write-instructions').hidden = false;
|
||||||
} else {
|
} else {
|
||||||
nmDoneStatus.textContent = 'Your NickelMenu package is ready to download.';
|
nmDoneStatus.textContent = TL.STATUS.NM_DOWNLOAD_READY;
|
||||||
triggerDownload(resultNmZip, 'NickelMenu-install.zip', 'application/zip');
|
triggerDownload(resultNmZip, 'NickelMenu-install.zip', 'application/zip');
|
||||||
$('nm-download-instructions').hidden = false;
|
$('nm-download-instructions').hidden = false;
|
||||||
// Show eReader.conf step only when sample config is included
|
// Show eReader.conf step only when sample config is included
|
||||||
@@ -689,13 +687,11 @@ import JSZip from 'jszip';
|
|||||||
|
|
||||||
function goToBuild() {
|
function goToBuild() {
|
||||||
if (isRestore) {
|
if (isRestore) {
|
||||||
firmwareDescription.textContent =
|
firmwareDescription.textContent = TL.STATUS.RESTORE_ORIGINAL;
|
||||||
'will be downloaded and extracted without modifications to restore the original unpatched software.';
|
btnBuild.textContent = TL.BUTTON.RESTORE_ORIGINAL;
|
||||||
btnBuild.textContent = 'Restore Original Software';
|
|
||||||
} else {
|
} else {
|
||||||
firmwareDescription.textContent =
|
firmwareDescription.textContent = TL.STATUS.FIRMWARE_WILL_BE_DOWNLOADED;
|
||||||
'will be downloaded automatically from Kobo\u2019s servers and will be patched after the download completes.';
|
btnBuild.textContent = TL.BUTTON.BUILD_PATCHED;
|
||||||
btnBuild.textContent = 'Build Patched Software';
|
|
||||||
}
|
}
|
||||||
populateSelectedPatchesList();
|
populateSelectedPatchesList();
|
||||||
setNavStep(4);
|
setNavStep(4);
|
||||||
@@ -705,7 +701,7 @@ import JSZip from 'jszip';
|
|||||||
btnBuildBack.addEventListener('click', () => {
|
btnBuildBack.addEventListener('click', () => {
|
||||||
if (isRestore) {
|
if (isRestore) {
|
||||||
isRestore = false;
|
isRestore = false;
|
||||||
setNavLabels(NAV_DEFAULT);
|
setNavLabels(TL.NAV_DEFAULT);
|
||||||
setNavStep(1);
|
setNavStep(1);
|
||||||
showStep(stepDevice);
|
showStep(stepDevice);
|
||||||
} else {
|
} else {
|
||||||
@@ -729,7 +725,7 @@ import JSZip from 'jszip';
|
|||||||
|
|
||||||
const contentLength = resp.headers.get('Content-Length');
|
const contentLength = resp.headers.get('Content-Length');
|
||||||
if (!contentLength || !resp.body) {
|
if (!contentLength || !resp.body) {
|
||||||
buildProgress.textContent = 'Downloading software update...';
|
buildProgress.textContent = TL.STATUS.DOWNLOADING;
|
||||||
return new Uint8Array(await resp.arrayBuffer());
|
return new Uint8Array(await resp.arrayBuffer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,8 +740,7 @@ import JSZip from 'jszip';
|
|||||||
chunks.push(value);
|
chunks.push(value);
|
||||||
received += value.length;
|
received += value.length;
|
||||||
const pct = ((received / total) * 100).toFixed(0);
|
const pct = ((received / total) * 100).toFixed(0);
|
||||||
buildProgress.textContent =
|
buildProgress.textContent = TL.STATUS.DOWNLOADING_PROGRESS(formatMB(received), formatMB(total), pct);
|
||||||
`Downloading software update... ${formatMB(received)} / ${formatMB(total)} (${pct}%)`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = new Uint8Array(received);
|
const result = new Uint8Array(received);
|
||||||
@@ -758,18 +753,18 @@ import JSZip from 'jszip';
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function extractOriginalTgz(firmwareBytes) {
|
async function extractOriginalTgz(firmwareBytes) {
|
||||||
buildProgress.textContent = 'Extracting KoboRoot.tgz...';
|
buildProgress.textContent = TL.STATUS.EXTRACTING;
|
||||||
appendLog('Extracting original KoboRoot.tgz from software update...');
|
appendLog('Extracting original KoboRoot.tgz from firmware...');
|
||||||
const zip = await JSZip.loadAsync(firmwareBytes);
|
const zip = await JSZip.loadAsync(firmwareBytes);
|
||||||
const koboRoot = zip.file('KoboRoot.tgz');
|
const koboRoot = zip.file('KoboRoot.tgz');
|
||||||
if (!koboRoot) throw new Error('KoboRoot.tgz not found in software update');
|
if (!koboRoot) throw new Error(TL.STATUS.EXTRACT_FAILED);
|
||||||
const tgz = new Uint8Array(await koboRoot.async('arraybuffer'));
|
const tgz = new Uint8Array(await koboRoot.async('arraybuffer'));
|
||||||
appendLog('Extracted KoboRoot.tgz: ' + formatMB(tgz.length));
|
appendLog('Extracted KoboRoot.tgz: ' + formatMB(tgz.length));
|
||||||
return tgz;
|
return tgz;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runPatcher(firmwareBytes) {
|
async function runPatcher(firmwareBytes) {
|
||||||
buildProgress.textContent = 'Applying patches...';
|
buildProgress.textContent = TL.STATUS.APPLYING_PATCHES;
|
||||||
const configYAML = patchUI.generateConfig();
|
const configYAML = patchUI.generateConfig();
|
||||||
const patchFiles = patchUI.getPatchFileBytes();
|
const patchFiles = patchUI.getPatchFileBytes();
|
||||||
|
|
||||||
@@ -804,7 +799,7 @@ import JSZip from 'jszip';
|
|||||||
btnWrite.hidden = manualMode;
|
btnWrite.hidden = manualMode;
|
||||||
btnWrite.disabled = false;
|
btnWrite.disabled = false;
|
||||||
btnWrite.className = 'primary';
|
btnWrite.className = 'primary';
|
||||||
btnWrite.textContent = 'Write to Kobo';
|
btnWrite.textContent = TL.BUTTON.WRITE_TO_DEVICE;
|
||||||
btnDownload.disabled = false;
|
btnDownload.disabled = false;
|
||||||
writeInstructions.hidden = true;
|
writeInstructions.hidden = true;
|
||||||
downloadInstructions.hidden = true;
|
downloadInstructions.hidden = true;
|
||||||
@@ -832,14 +827,14 @@ import JSZip from 'jszip';
|
|||||||
btnBuild.addEventListener('click', async () => {
|
btnBuild.addEventListener('click', async () => {
|
||||||
showStep(stepBuilding, false);
|
showStep(stepBuilding, false);
|
||||||
buildLog.textContent = '';
|
buildLog.textContent = '';
|
||||||
buildProgress.textContent = 'Starting...';
|
buildProgress.textContent = TL.STATUS.BUILDING_STARTING;
|
||||||
$('build-wait-hint').textContent = isRestore
|
$('build-wait-hint').textContent = isRestore
|
||||||
? 'Please wait while the original software is being downloaded and extracted...'
|
? 'Please wait while the original software is being downloaded and extracted...'
|
||||||
: 'Please wait while the patch is being applied...';
|
: 'Please wait while the patch is being applied...';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!firmwareURL) {
|
if (!firmwareURL) {
|
||||||
showError('No download URL available for this device.');
|
showError(TL.STATUS.NO_FIRMWARE_URL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,7 +857,7 @@ import JSZip from 'jszip';
|
|||||||
if (!resultTgz || !device.directoryHandle) return;
|
if (!resultTgz || !device.directoryHandle) return;
|
||||||
|
|
||||||
btnWrite.disabled = true;
|
btnWrite.disabled = true;
|
||||||
btnWrite.textContent = 'Writing...';
|
btnWrite.textContent = TL.BUTTON.WRITING;
|
||||||
downloadInstructions.hidden = true;
|
downloadInstructions.hidden = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -872,13 +867,13 @@ import JSZip from 'jszip';
|
|||||||
await writable.write(resultTgz);
|
await writable.write(resultTgz);
|
||||||
await writable.close();
|
await writable.close();
|
||||||
|
|
||||||
btnWrite.textContent = 'Written';
|
btnWrite.textContent = TL.BUTTON.WRITTEN;
|
||||||
btnWrite.className = 'btn-success';
|
btnWrite.className = 'btn-success';
|
||||||
writeInstructions.hidden = false;
|
writeInstructions.hidden = false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
btnWrite.disabled = false;
|
btnWrite.disabled = false;
|
||||||
btnWrite.textContent = 'Write to Kobo';
|
btnWrite.textContent = TL.BUTTON.WRITE_TO_DEVICE;
|
||||||
showError('Failed to write KoboRoot.tgz: ' + err.message);
|
showError(TL.STATUS.WRITE_FAILED + err.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -905,12 +900,12 @@ import JSZip from 'jszip';
|
|||||||
|
|
||||||
const hasBackStep = stepHistory.includes(stepPatches);
|
const hasBackStep = stepHistory.includes(stepPatches);
|
||||||
if (hasBackStep) {
|
if (hasBackStep) {
|
||||||
errorTitle.textContent = 'The patch failed to apply';
|
errorTitle.textContent = TL.ERROR.PATCH_FAILED;
|
||||||
errorHint.hidden = false;
|
errorHint.hidden = false;
|
||||||
btnErrorBack.hidden = false;
|
btnErrorBack.hidden = false;
|
||||||
btnRetry.classList.add('danger');
|
btnRetry.classList.add('danger');
|
||||||
} else {
|
} else {
|
||||||
errorTitle.textContent = 'Something went wrong';
|
errorTitle.textContent = TL.ERROR.SOMETHING_WENT_WRONG;
|
||||||
errorHint.hidden = true;
|
errorHint.hidden = true;
|
||||||
btnErrorBack.hidden = true;
|
btnErrorBack.hidden = true;
|
||||||
btnRetry.classList.remove('danger');
|
btnRetry.classList.remove('danger');
|
||||||
@@ -944,7 +939,7 @@ import JSZip from 'jszip';
|
|||||||
btnDeviceNext.hidden = false;
|
btnDeviceNext.hidden = false;
|
||||||
btnDeviceRestore.hidden = false;
|
btnDeviceRestore.hidden = false;
|
||||||
|
|
||||||
setNavLabels(NAV_DEFAULT);
|
setNavLabels(TL.NAV_DEFAULT);
|
||||||
setNavStep(1);
|
setNavStep(1);
|
||||||
showStep(stepConnect);
|
showStep(stepConnect);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import JSZip from 'jszip';
|
import JSZip from 'jszip';
|
||||||
|
import { TL } from './strings.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Friendly display names for patch files.
|
* Friendly display names for patch files.
|
||||||
@@ -288,7 +289,7 @@ class PatchUI {
|
|||||||
});
|
});
|
||||||
const noneName = document.createElement('span');
|
const noneName = document.createElement('span');
|
||||||
noneName.className = 'patch-name patch-name-none';
|
noneName.className = 'patch-name patch-name-none';
|
||||||
noneName.textContent = 'None (do not patch)';
|
noneName.textContent = TL.PATCH.NONE;
|
||||||
noneHeader.appendChild(noneInput);
|
noneHeader.appendChild(noneInput);
|
||||||
noneHeader.appendChild(noneName);
|
noneHeader.appendChild(noneName);
|
||||||
noneItem.appendChild(noneHeader);
|
noneItem.appendChild(noneHeader);
|
||||||
|
|||||||
59
web/src/js/strings.js
Normal file
59
web/src/js/strings.js
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
export const TL = {
|
||||||
|
NAV_NICKELMENU: ['Device', 'Mode', 'Configure', 'Review', 'Install'],
|
||||||
|
NAV_PATCHES: ['Device', 'Mode', 'Patches', 'Build', 'Install'],
|
||||||
|
NAV_DEFAULT: ['Device', 'Mode', 'Patches', 'Build', 'Install'],
|
||||||
|
|
||||||
|
BUTTON: {
|
||||||
|
RESTORE_ORIGINAL: 'Restore Original Software',
|
||||||
|
BUILD_PATCHED: 'Build Patched Software',
|
||||||
|
WRITE_TO_DEVICE: 'Write to Kobo',
|
||||||
|
REMOVE_FROM_KOBO: 'Remove from Kobo',
|
||||||
|
WRITING: 'Writing...',
|
||||||
|
WRITTEN: 'Written',
|
||||||
|
GO_BACK: '\u2039 Back',
|
||||||
|
SELECT_DIFFERENT_PATCHES: '\u2039 Select different patches',
|
||||||
|
},
|
||||||
|
|
||||||
|
STATUS: {
|
||||||
|
DEVICE_RECOGNIZED: 'Your device has been recognized. You can continue to the next step!',
|
||||||
|
NM_REMOVED_ON_REBOOT: 'NickelMenu will be removed on next reboot.',
|
||||||
|
NM_INSTALLED: 'NickelMenu has been installed on your Kobo.',
|
||||||
|
NM_DOWNLOAD_READY: 'Your NickelMenu package is ready to download.',
|
||||||
|
NM_WILL_BE_REMOVED: 'NickelMenu will be updated and marked for removal. It will uninstall itself when your Kobo reboots.',
|
||||||
|
NM_WILL_BE_INSTALLED: 'The following will be installed on your Kobo:',
|
||||||
|
NM_NICKEL_ROOT_TGZ: 'NickelMenu (KoboRoot.tgz)',
|
||||||
|
NM_REMOVAL_HINT: 'Removes NickelMenu from your device. You must restart your Kobo to complete the uninstall!',
|
||||||
|
NM_REMOVAL_DISABLED: 'Removes NickelMenu from your device. Only available when a Kobo with NickelMenu installed is connected.',
|
||||||
|
PATCH_COUNT_ZERO: 'No patches selected \u2014 continuing will restore the original unpatched software.',
|
||||||
|
PATCH_COUNT_ONE: '1 patch selected.',
|
||||||
|
PATCH_COUNT_MULTI: (n) => `${n} patches selected.`,
|
||||||
|
FIRMWARE_WILL_BE_DOWNLOADED: 'will be downloaded automatically from Kobo\u2019s servers and will be patched after the download completes.',
|
||||||
|
RESTORE_ORIGINAL: 'will be downloaded and extracted without modifications to restore the original unpatched software.',
|
||||||
|
BUILDING_STARTING: 'Starting...',
|
||||||
|
DOWNLOADING: 'Downloading software update...',
|
||||||
|
DOWNLOADING_PROGRESS: (received, total, pct) => `Downloading software update... ${received} / ${total} (${pct}%)`,
|
||||||
|
EXTRACTING: 'Extracting KoboRoot.tgz...',
|
||||||
|
APPLYING_PATCHES: 'Applying patches...',
|
||||||
|
NO_FIRMWARE_URL: 'No download URL available for this device.',
|
||||||
|
WRITE_FAILED: 'Failed to write KoboRoot.tgz: ',
|
||||||
|
NM_INSTALL_FAILED: 'NickelMenu installation failed: ',
|
||||||
|
EXTRACT_FAILED: 'KoboRoot.tgz not found in software update',
|
||||||
|
},
|
||||||
|
|
||||||
|
ERROR: {
|
||||||
|
PATCH_FAILED: 'The patch failed to apply',
|
||||||
|
SOMETHING_WENT_WRONG: 'Something went wrong',
|
||||||
|
LOAD_PATCHES_FAILED: (v) => `Could not load patches for software version ${v}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
PATCH: {
|
||||||
|
NONE: 'None (do not patch)',
|
||||||
|
},
|
||||||
|
|
||||||
|
NICKEL_MENU_ITEMS: {
|
||||||
|
FONTS: 'Readerly fonts',
|
||||||
|
SCREENSAVER: 'Custom screensaver',
|
||||||
|
SIMPLIFY_TABS: 'Simplified tab menu',
|
||||||
|
SIMPLIFY_HOME: 'Simplified homescreen',
|
||||||
|
},
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user