Translate 1002 errors. Always starts with translation for "connection refused: " followed by translated error.

Cosmetic.reason isn't translated, doesn't seem like going another level deeper really helps.

Add translated tips if turnstile is invalid.

Append English error for screenshots so devs understand what error user gets.
This commit is contained in:
VariableVince
2026-05-06 22:25:59 +02:00
parent b05f8ea5d0
commit 9dadb1ebd3
4 changed files with 56 additions and 18 deletions
+12
View File
@@ -1219,5 +1219,17 @@
"fullscreen": {
"enter": "Enter fullscreen",
"exit": "Exit fullscreen"
},
"worker_error": {
"account_banned": "Account Banned",
"cannot_join_game": "Cannot join game",
"connection_refused": "Connection refused",
"flare_forbidden": "Forbidden",
"game_not_found": "Game not found",
"lobby_full": "Lobby full",
"turnstile_invalid": "Unauthorized: invalid token",
"turnstile_fix_tips": "Try this to fix: \n 1. Do a hard refresh (Mac: Cmd+Shift+R, Windows: Ctrl+F5) \n 2. Or resync your device clock \n 3. Or close all browser windows and restart your browser \n 4. Or try another browser, preferably without extensions \n 5. Or clear site data for this site",
"unauthorized": "Unauthorized",
"user_me_fetch_failed": "Unauthorized: user fetch failed"
}
}
+24 -1
View File
@@ -29,6 +29,7 @@ import { replacer } from "../core/Util";
import { getPlayToken } from "./Auth";
import { LobbyConfig } from "./ClientGameRunner";
import { LocalServer } from "./LocalServer";
import { getEnglishText, translateText } from "./Utils";
export class PauseGameIntentEvent implements GameEvent {
constructor(public readonly paused: boolean) {}
@@ -378,8 +379,30 @@ export class Transport {
`WebSocket closed. Code: ${event.code}, Reason: ${event.reason}`,
);
if (event.code === 1002) {
const connRefusedKey = `worker_error.connection_refused`;
let alertMsg = translateText(connRefusedKey);
const errorKey = `worker_error.${event.reason}`;
alertMsg += `: ${translateText(errorKey)}`;
// Add tips if turnstile token invalid
if (event.reason === "turnstile_invalid") {
alertMsg += `\n\n${translateText("worker_error.turnstile_fix_tips")}`;
}
// Append English error if it differs, for screenshots posted by users
const englishMsg = getEnglishText(errorKey);
if (!alertMsg.includes(englishMsg)) {
const englishConnRefusedMsg = getEnglishText(connRefusedKey);
alertMsg += `\n\n--- English ---\n${englishConnRefusedMsg}: `;
if (englishMsg !== errorKey) {
alertMsg += `${englishMsg}`;
} else if (englishMsg === errorKey) {
alertMsg += `${event.reason}`;
}
}
// TODO: make this a modal
alert(`connection refused: ${event.reason}`);
alert(alertMsg);
} else if (event.code !== 1000) {
console.log(`received error code ${event.code}, reconnecting`);
this.reconnect();
+10 -1
View File
@@ -12,6 +12,7 @@ import {
import { GameConfig } from "../core/Schemas";
import type { LangSelector } from "./LangSelector";
import { Platform } from "./Platform";
import { get } from "http";
export const TUTORIAL_VIDEO_URL = "https://www.youtube.com/embed/EN2oOog3pSs";
@@ -407,9 +408,17 @@ function getCachedLangSelector(): LangSelector | null {
return found;
}
export function getEnglishText(
key: string,
params?: Record<string, string | number>,
): string {
return translateText(key, params, true);
}
export const translateText = (
key: string,
params?: Record<string, string | number>,
getOnlyEnglish: boolean = false,
): string => {
const self = translateText as any;
self.formatterCache ??= new Map();
@@ -436,7 +445,7 @@ export const translateText = (
self.lastLang = langSelector.currentLang;
}
let message = translations?.[key];
let message = getOnlyEnglish ? undefined : translations?.[key];
const hasPrimaryTranslation = message !== undefined;
message ??= defaultTranslations?.[key];
+10 -16
View File
@@ -330,16 +330,13 @@ export async function startWorker() {
log.warn(`Invalid token: ${result.message}`, {
gameID: clientMsg.gameID,
});
ws.close(
1002,
"Unauthorized: invalid token \n\n Try this to fix: \n 1. Do a hard refresh (Mac: Cmd+Shift+R, Windows: Ctrl+F5) \n 2. Or resync your device clock \n 3. Or close all browser windows and restart your browser \n 4. Or try another browser, preferably without extensions \n 5. Or clear site data for this site",
);
ws.close(1002, "turnstile_invalid");
return;
}
const { persistentId, claims } = result;
if (claims?.role === "banned") {
ws.close(1002, "Account Banned");
ws.close(1002, "account_banned");
return;
}
@@ -358,7 +355,7 @@ export async function startWorker() {
log.warn(
`game ${clientMsg.gameID} not found on worker ${workerId}`,
);
ws.close(1002, "Game not found");
ws.close(1002, "game_not_found");
}
return;
}
@@ -388,7 +385,7 @@ export async function startWorker() {
if (claims === null) {
if (allowedFlares !== undefined) {
log.warn("Unauthorized: Anonymous user attempted to join game");
ws.close(1002, "Unauthorized");
ws.close(1002, "unauthorized");
return;
}
} else {
@@ -399,7 +396,7 @@ export async function startWorker() {
persistentID: persistentId,
gameID: clientMsg.gameID,
});
ws.close(1002, "Unauthorized: user me fetch failed");
ws.close(1002, "user_me_fetch_failed");
return;
}
flares = result.response.player.flares;
@@ -412,7 +409,7 @@ export async function startWorker() {
log.warn(
"Forbidden: player without an allowed flare attempted to join game",
);
ws.close(1002, "Forbidden");
ws.close(1002, "forbidden");
return;
}
}
@@ -446,10 +443,7 @@ export async function startWorker() {
gameID: clientMsg.gameID,
reason: turnstileResult.reason,
});
ws.close(
1002,
"Unauthorized: Turnstile token rejected \n\n Try this to fix: \n 1. Do a hard refresh (Mac: Cmd+Shift+R, Windows: Ctrl+F5) \n 2. Or resync your device clock \n 3. Or close all browser windows and restart your browser \n 4. Or try another browser, preferably without extensions \n 5. Or clear site data for this site",
);
ws.close(1002, "turnstile_invalid");
return;
case "error":
// Fail open, allow the client to join.
@@ -479,19 +473,19 @@ export async function startWorker() {
if (joinResult === "not_found") {
log.info(`game ${clientMsg.gameID} not found on worker ${workerId}`);
ws.close(1002, "Game not found");
ws.close(1002, "game_not_found");
} else if (joinResult === "kicked") {
log.warn(`kicked client tried to join game ${clientMsg.gameID}`, {
gameID: clientMsg.gameID,
workerId,
});
ws.close(1002, "Cannot join game");
ws.close(1002, "cannot_join_game");
} else if (joinResult === "rejected") {
log.info(`client rejected from game ${clientMsg.gameID}`, {
gameID: clientMsg.gameID,
workerId,
});
ws.close(1002, "Lobby full");
ws.close(1002, "lobby_full");
}
// Handle other message types