mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
Translate Spanish text to English across docs and code
This commit is contained in:
@@ -56,7 +56,7 @@ export function parseEnvIntInRange(name: string, fallback: number, min: number,
|
||||
|
||||
const parsedValue = Number.parseInt(rawValue, 10);
|
||||
if (!Number.isFinite(parsedValue) || parsedValue < min || parsedValue > max) {
|
||||
throw new Error(`La variable ${name} debe ser un entero entre ${min} y ${max}. Valor recibido: '${rawValue}'.`);
|
||||
throw new Error(`The ${name} variable must be an integer between ${min} and ${max}. Received value: '${rawValue}'.`);
|
||||
}
|
||||
|
||||
return parsedValue;
|
||||
@@ -68,7 +68,7 @@ export function parseEnvPort(name: string, fallback: string): string {
|
||||
|
||||
if (!Number.isFinite(parsedValue) || parsedValue < MIN_TCP_PORT || parsedValue > MAX_TCP_PORT) {
|
||||
throw new Error(
|
||||
`La variable ${name} debe ser un puerto TCP válido (${MIN_TCP_PORT}-${MAX_TCP_PORT}). Valor recibido: '${rawValue}'.`,
|
||||
`The ${name} variable must be a valid TCP port (${MIN_TCP_PORT}-${MAX_TCP_PORT}). Received value: '${rawValue}'.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -146,9 +146,9 @@ process.on("exit", () => {
|
||||
});
|
||||
|
||||
process.on("uncaughtException", (error) => {
|
||||
showFatalError("Error inesperado en el proceso principal de Electron.", error);
|
||||
showFatalError("Unexpected error in Electron main process.", error);
|
||||
});
|
||||
|
||||
process.on("unhandledRejection", (reason) => {
|
||||
showFatalError("Promesa no controlada en el proceso principal de Electron.", reason);
|
||||
showFatalError("Unhandled promise in Electron main process.", reason);
|
||||
});
|
||||
|
||||
@@ -64,7 +64,7 @@ export function createNodecgProcessManager({
|
||||
const isPortAvailable = await resolvedDeps.probePortAvailable(portAsNumber);
|
||||
if (!isPortAvailable) {
|
||||
throw new Error(
|
||||
`El puerto ${appConfig.nodecgPort} ya está en uso. Cierra el proceso que lo ocupa o configura NODECG_PORT antes de iniciar.`,
|
||||
`Port ${appConfig.nodecgPort} is already in use. Stop the process using it or set NODECG_PORT before starting.`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -110,16 +110,16 @@ export function createNodecgProcessManager({
|
||||
while (Date.now() - startTime < appConfig.startupTimeoutMs) {
|
||||
if (!nodecgProcess) {
|
||||
const exitDetails = lastExit
|
||||
? `Última salida registrada: code=${lastExit.code ?? "null"}, signal=${lastExit.signal ?? "none"}.`
|
||||
: "No se registró código de salida del proceso NodeCG.";
|
||||
const stderrDetails = lastStderrLine ? `Último stderr: ${lastStderrLine}` : "Sin salida stderr capturada.";
|
||||
? `Last recorded exit: code=${lastExit.code ?? "null"}, signal=${lastExit.signal ?? "none"}.`
|
||||
: "No NodeCG process exit code was recorded.";
|
||||
const stderrDetails = lastStderrLine ? `Last stderr: ${lastStderrLine}` : "No stderr output captured.";
|
||||
throw new Error(
|
||||
[
|
||||
"NodeCG terminó antes de estar listo.",
|
||||
"NodeCG exited before becoming ready.",
|
||||
exitDetails,
|
||||
stderrDetails,
|
||||
`Ruta NodeCG: ${nodecgRootPath}`,
|
||||
"Revisa que lib/nodecg tenga dependencias instaladas y que el bundle exista.",
|
||||
`NodeCG path: ${nodecgRootPath}`,
|
||||
"Check that lib/nodecg dependencies are installed and the bundle exists.",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export function createNodecgProcessManager({
|
||||
await sleep(500, resolvedDeps.setTimer);
|
||||
}
|
||||
|
||||
throw new Error(`Timeout esperando NodeCG en ${nodecgBaseUrl} (${appConfig.startupTimeoutMs}ms).`);
|
||||
throw new Error(`Timeout waiting for NodeCG at ${nodecgBaseUrl} (${appConfig.startupTimeoutMs}ms).`);
|
||||
};
|
||||
|
||||
const stopNodecgProcessGracefully = (): Promise<void> => {
|
||||
@@ -223,23 +223,23 @@ function validateNodecgInstall(
|
||||
const bundlePath = path.join(nodecgRootPath, "bundles", bundleName);
|
||||
|
||||
if (!pathExists(nodecgRootPath)) {
|
||||
throw new Error(`No existe la carpeta NodeCG: ${nodecgRootPath}`);
|
||||
throw new Error(`NodeCG folder does not exist: ${nodecgRootPath}`);
|
||||
}
|
||||
|
||||
if (!hasReadWriteAccessToPath(nodecgRootPath)) {
|
||||
throw new Error(`Sin permisos de lectura/escritura sobre NodeCG: ${nodecgRootPath}`);
|
||||
throw new Error(`No read/write permissions on NodeCG: ${nodecgRootPath}`);
|
||||
}
|
||||
|
||||
if (!pathExists(indexPath)) {
|
||||
throw new Error(`No se encontró ${indexPath}. Copia una instalación completa de NodeCG en lib/nodecg.`);
|
||||
throw new Error(`${indexPath} was not found. Copy a full NodeCG installation into lib/nodecg.`);
|
||||
}
|
||||
|
||||
if (!pathExists(nodecgBootstrapPath)) {
|
||||
throw new Error(
|
||||
[
|
||||
"NodeCG está presente pero faltan dependencias internas.",
|
||||
`No existe: ${nodecgBootstrapPath}`,
|
||||
"Solución: entra a lib/nodecg e instala dependencias:",
|
||||
"NodeCG is present but internal dependencies are missing.",
|
||||
`Not found: ${nodecgBootstrapPath}`,
|
||||
"Solution: enter lib/nodecg and install dependencies:",
|
||||
" npm install",
|
||||
].join("\n"),
|
||||
);
|
||||
@@ -248,9 +248,9 @@ function validateNodecgInstall(
|
||||
if (!pathExists(bundlePath)) {
|
||||
throw new Error(
|
||||
[
|
||||
`No se encontró el bundle '${bundleName}'.`,
|
||||
`Ruta esperada: ${bundlePath}`,
|
||||
"Copia/clona tu bundle dentro de lib/nodecg/bundles antes de ejecutar Electron.",
|
||||
`Bundle '${bundleName}' was not found.`,
|
||||
`Expected path: ${bundlePath}`,
|
||||
"Copy/clone your bundle inside lib/nodecg/bundles before running Electron.",
|
||||
].join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ function getBaseConfig(): AppRuntimeConfig {
|
||||
};
|
||||
}
|
||||
|
||||
test("resolveAppIconPath prioriza iconPathOverride cuando existe", () => {
|
||||
test("resolveAppIconPath prioritizes iconPathOverride when present", () => {
|
||||
const appConfig: AppRuntimeConfig = {
|
||||
...getBaseConfig(),
|
||||
iconPathOverride: "/custom/icon.ico",
|
||||
@@ -30,7 +30,7 @@ test("resolveAppIconPath prioriza iconPathOverride cuando existe", () => {
|
||||
assert.equal(iconPath, "/custom/icon.ico");
|
||||
});
|
||||
|
||||
test("resolveAppIconPath cae al primer icono por defecto existente", () => {
|
||||
test("resolveAppIconPath falls back to the first existing default icon", () => {
|
||||
const appConfig = getBaseConfig();
|
||||
const expectedIconPath = path.join("/app", "static", "icons", "icon.png");
|
||||
|
||||
@@ -39,7 +39,7 @@ test("resolveAppIconPath cae al primer icono por defecto existente", () => {
|
||||
assert.equal(iconPath, expectedIconPath);
|
||||
});
|
||||
|
||||
test("resolveAppIconPath devuelve undefined cuando no hay iconos", () => {
|
||||
test("resolveAppIconPath returns undefined when no icons exist", () => {
|
||||
const appConfig = getBaseConfig();
|
||||
|
||||
const iconPath = resolveAppIconPath(appConfig, "/app", () => false);
|
||||
|
||||
@@ -5,37 +5,37 @@ import { shouldAllowInternalNavigation, shouldOpenExternalNavigation } from "../
|
||||
|
||||
const dashboardUrl = "http://localhost:9090/bundles/scoreko-dev/dashboard/main.html";
|
||||
|
||||
test("shouldAllowInternalNavigation permite navegación interna esperada", () => {
|
||||
test("shouldAllowInternalNavigation allows expected internal navigation", () => {
|
||||
assert.equal(
|
||||
shouldAllowInternalNavigation("http://127.0.0.1:9090/bundles/scoreko-dev/dashboard/page.html", dashboardUrl),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldAllowInternalNavigation rechaza host no permitido", () => {
|
||||
test("shouldAllowInternalNavigation rejects disallowed host", () => {
|
||||
assert.equal(
|
||||
shouldAllowInternalNavigation("http://evil.local:9090/bundles/scoreko-dev/dashboard/page.html", dashboardUrl),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldAllowInternalNavigation rechaza puerto distinto", () => {
|
||||
test("shouldAllowInternalNavigation rejects different port", () => {
|
||||
assert.equal(
|
||||
shouldAllowInternalNavigation("http://localhost:8080/bundles/scoreko-dev/dashboard/page.html", dashboardUrl),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
test("shouldAllowInternalNavigation rechaza esquemas inseguros", () => {
|
||||
test("shouldAllowInternalNavigation rejects unsafe schemes", () => {
|
||||
assert.equal(shouldAllowInternalNavigation("javascript:alert(1)", dashboardUrl), false);
|
||||
});
|
||||
|
||||
test("shouldOpenExternalNavigation permite protocolos externos seguros", () => {
|
||||
test("shouldOpenExternalNavigation allows safe external protocols", () => {
|
||||
assert.equal(shouldOpenExternalNavigation("https://scoreko.com/docs"), true);
|
||||
assert.equal(shouldOpenExternalNavigation("mailto:test@scoreko.com"), true);
|
||||
});
|
||||
|
||||
test("shouldOpenExternalNavigation rechaza protocolos inseguros", () => {
|
||||
test("shouldOpenExternalNavigation rejects unsafe protocols", () => {
|
||||
assert.equal(shouldOpenExternalNavigation("file:///etc/passwd"), false);
|
||||
assert.equal(shouldOpenExternalNavigation("javascript:alert(1)"), false);
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ function getBaseConfig(): AppRuntimeConfig {
|
||||
};
|
||||
}
|
||||
|
||||
test("startNodeCG valida instalación de NodeCG antes de arrancar", async () => {
|
||||
test("startNodeCG validates NodeCG installation before starting", async () => {
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
nodecgRootPath: "/fake/nodecg",
|
||||
@@ -41,17 +41,17 @@ test("startNodeCG valida instalación de NodeCG antes de arrancar", async () =>
|
||||
deps: {
|
||||
pathExists: () => false,
|
||||
spawnProcess: () => {
|
||||
throw new Error("no debe intentar arrancar si la validación falla");
|
||||
throw new Error("it must not try to start if validation fails");
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await assert.rejects(async () => {
|
||||
await manager.startNodecgProcess();
|
||||
}, /No existe la carpeta NodeCG/);
|
||||
}, /NodeCG folder does not exist/);
|
||||
});
|
||||
|
||||
test("startNodeCG falla si no hay permisos de lectura/escritura", async () => {
|
||||
test("startNodeCG fails when there are no read/write permissions", async () => {
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
nodecgRootPath: "/fake/nodecg",
|
||||
@@ -66,10 +66,10 @@ test("startNodeCG falla si no hay permisos de lectura/escritura", async () => {
|
||||
|
||||
await assert.rejects(async () => {
|
||||
await manager.startNodecgProcess();
|
||||
}, /Sin permisos de lectura\/escritura/);
|
||||
}, /No read\/write permissions on NodeCG/);
|
||||
});
|
||||
|
||||
test("waitForNodeCGReady resuelve cuando el endpoint responde 404", async () => {
|
||||
test("waitForNodeCGReady resolves when endpoint returns 404", async () => {
|
||||
const child = new MockChildProcess(4321);
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
@@ -99,7 +99,7 @@ test("waitForNodeCGReady resuelve cuando el endpoint responde 404", async () =>
|
||||
});
|
||||
});
|
||||
|
||||
test("stopNodeCG envía SIGTERM y luego SIGKILL si el proceso no sale", async () => {
|
||||
test("stopNodeCG sends SIGTERM and then SIGKILL if the process does not exit", async () => {
|
||||
const child = new MockChildProcess(9999);
|
||||
const timers: Array<() => void> = [];
|
||||
const killSignals: Array<{ pid: number; signal: NodeJS.Signals }> = [];
|
||||
@@ -147,7 +147,7 @@ test("stopNodeCG envía SIGTERM y luego SIGKILL si el proceso no sale", async ()
|
||||
await stopPromise;
|
||||
});
|
||||
|
||||
test("stopNodeCG reutiliza la misma promesa cuando se invoca en paralelo", async () => {
|
||||
test("stopNodeCG reuses the same promise when invoked in parallel", async () => {
|
||||
const child = new MockChildProcess(5555);
|
||||
|
||||
const manager = createNodecgProcessManager({
|
||||
@@ -179,7 +179,7 @@ test("stopNodeCG reutiliza la misma promesa cuando se invoca en paralelo", async
|
||||
await firstStop;
|
||||
});
|
||||
|
||||
test("stopNodeCG normaliza timeout negativo a cero", async () => {
|
||||
test("stopNodeCG normalizes negative timeout to zero", async () => {
|
||||
const child = new MockChildProcess(7777);
|
||||
const timeouts: number[] = [];
|
||||
|
||||
@@ -218,7 +218,7 @@ test("stopNodeCG normaliza timeout negativo a cero", async () => {
|
||||
await stopPromise;
|
||||
});
|
||||
|
||||
test("startNodeCG falla si el puerto ya está ocupado", async () => {
|
||||
test("startNodeCG fails if the port is already in use", async () => {
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
nodecgRootPath: "/fake/nodecg",
|
||||
@@ -234,10 +234,10 @@ test("startNodeCG falla si el puerto ya está ocupado", async () => {
|
||||
|
||||
await assert.rejects(async () => {
|
||||
await manager.startNodecgProcess();
|
||||
}, /ya está en uso/);
|
||||
}, /is already in use/);
|
||||
});
|
||||
|
||||
test("waitForNodeCGReady expone diagnóstico cuando NodeCG sale antes de readiness", async () => {
|
||||
test("waitForNodeCGReady exposes diagnostics when NodeCG exits before readiness", async () => {
|
||||
const child = new MockChildProcess(4242);
|
||||
const manager = createNodecgProcessManager({
|
||||
isDev: true,
|
||||
@@ -272,9 +272,9 @@ test("waitForNodeCGReady expone diagnóstico cuando NodeCG sale antes de readine
|
||||
},
|
||||
(error: unknown) => {
|
||||
assert.ok(error instanceof Error);
|
||||
assert.match(error.message, /NodeCG terminó antes de estar listo/);
|
||||
assert.match(error.message, /Última salida registrada/);
|
||||
assert.match(error.message, /Ruta NodeCG: \/fake\/nodecg/);
|
||||
assert.match(error.message, /NodeCG exited before becoming ready/);
|
||||
assert.match(error.message, /Last recorded exit/);
|
||||
assert.match(error.message, /NodeCG path: \/fake\/nodecg/);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
|
||||
@@ -24,61 +24,61 @@ function withEnv(name: string, value: string | undefined, run: () => void): void
|
||||
}
|
||||
}
|
||||
|
||||
test("getOptionalEnv devuelve undefined para variable ausente", () => {
|
||||
test("getOptionalEnv returns undefined for missing variable", () => {
|
||||
withEnv("TEST_OPTIONAL_ENV", undefined, () => {
|
||||
assert.equal(getOptionalEnv("TEST_OPTIONAL_ENV"), undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test("getOptionalEnv recorta espacios y devuelve valor", () => {
|
||||
test("getOptionalEnv trims spaces and returns value", () => {
|
||||
withEnv("TEST_OPTIONAL_ENV", " scoreko ", () => {
|
||||
assert.equal(getOptionalEnv("TEST_OPTIONAL_ENV"), "scoreko");
|
||||
});
|
||||
});
|
||||
|
||||
test("getEnv devuelve fallback para valor vacío", () => {
|
||||
test("getEnv returns fallback for empty value", () => {
|
||||
withEnv("TEST_ENV", " ", () => {
|
||||
assert.equal(getEnv("TEST_ENV", "fallback"), "fallback");
|
||||
});
|
||||
});
|
||||
|
||||
test("getEnv devuelve el valor cuando existe", () => {
|
||||
withEnv("TEST_ENV", "valor", () => {
|
||||
assert.equal(getEnv("TEST_ENV", "fallback"), "valor");
|
||||
test("getEnv returns the value when present", () => {
|
||||
withEnv("TEST_ENV", "value", () => {
|
||||
assert.equal(getEnv("TEST_ENV", "fallback"), "value");
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvInt devuelve fallback para valores inválidos", () => {
|
||||
test("parseEnvInt returns fallback for invalid values", () => {
|
||||
withEnv("TEST_ENV_INT", "abc", () => {
|
||||
assert.equal(parseEnvInt("TEST_ENV_INT", 100), 100);
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvInt parsea enteros válidos", () => {
|
||||
test("parseEnvInt parses valid integers", () => {
|
||||
withEnv("TEST_ENV_INT", "4500", () => {
|
||||
assert.equal(parseEnvInt("TEST_ENV_INT", 100), 4500);
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvIntInRange hace hard-fail para valores fuera de rango", () => {
|
||||
test("parseEnvIntInRange hard-fails for out-of-range values", () => {
|
||||
withEnv("TEST_ENV_INT_RANGE", "999", () => {
|
||||
assert.throws(() => parseEnvIntInRange("TEST_ENV_INT_RANGE", 100, 0, 100), /debe ser un entero/);
|
||||
assert.throws(() => parseEnvIntInRange("TEST_ENV_INT_RANGE", 100, 0, 100), /must be an integer/);
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvIntInRange acepta valor válido", () => {
|
||||
test("parseEnvIntInRange accepts valid value", () => {
|
||||
withEnv("TEST_ENV_INT_RANGE", "42", () => {
|
||||
assert.equal(parseEnvIntInRange("TEST_ENV_INT_RANGE", 100, 0, 100), 42);
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvPort valida rango TCP", () => {
|
||||
test("parseEnvPort validates TCP range", () => {
|
||||
withEnv("TEST_ENV_PORT", "70000", () => {
|
||||
assert.throws(() => parseEnvPort("TEST_ENV_PORT", "9090"), /puerto TCP válido/);
|
||||
assert.throws(() => parseEnvPort("TEST_ENV_PORT", "9090"), /valid TCP port/);
|
||||
});
|
||||
});
|
||||
|
||||
test("parseEnvPort normaliza el puerto válido", () => {
|
||||
test("parseEnvPort normalizes valid port", () => {
|
||||
withEnv("TEST_ENV_PORT", "009090", () => {
|
||||
assert.equal(parseEnvPort("TEST_ENV_PORT", "9090"), "9090");
|
||||
});
|
||||
|
||||
@@ -3,12 +3,12 @@ import test from "node:test";
|
||||
|
||||
import { getRemainingDelayMs } from "../main/utils/timing";
|
||||
|
||||
test("getRemainingDelayMs devuelve el tiempo restante cuando aún no se cumple", () => {
|
||||
test("getRemainingDelayMs returns the remaining time when delay has not elapsed", () => {
|
||||
const remaining = getRemainingDelayMs(10000, 1000, 4000);
|
||||
assert.equal(remaining, 7000);
|
||||
});
|
||||
|
||||
test("getRemainingDelayMs devuelve 0 si ya pasó el delay", () => {
|
||||
test("getRemainingDelayMs returns 0 when delay has already elapsed", () => {
|
||||
const remaining = getRemainingDelayMs(1000, 1000, 5000);
|
||||
assert.equal(remaining, 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user