Files
JesseandClaude Opus 5 a70337cf8b 0.8.0.12:0 — bundle Station Master v0.8.0.12, and a Restore a Seat action
A player who has lost their browser storage can be put back in their seat
(Gitea#33 in the game repo). The session token is the only identity the game
has and it lives in one browser's localStorage, scoped to the origin joined at,
so a cleared profile, a private window or a different browser locks a player
out of a game that is still running with their session still on disk. Seen at a
real table: of two humans in one game, the host reloaded straight back in and
the joiner met an empty lobby.

New action, restore-seat: pick a seat from a dropdown of the players actually
holding a session — bots never appear, since seatedPlayers is read from the
server's session map rather than guessed from display names — and get back a
link built from this interface's own address. serverApi gained mintClaim; the
dictionary gained 57-64 in all five locales.

THE LINK CARRIES A CODE, NOT THE TOKEN. lobby-and-sessions.md §1 says to keep
the token out of URLs so it is not shoulder-surfed or pasted into a chat, and a
recovery link is exactly what gets pasted into a chat. The code is single-use,
expires in 30 minutes, and the page trades it for the real token over a POST.
Minting is admin-gated because deciding that somebody has lost a seat is a
judgement no route can make safely; spending needs no secret, because the
player following the link holds none.

GAMES IN PROGRESS RESUME NORMALLY, measured rather than assumed:
`git diff v0.8.0.11..v0.8.0.12 -- src/engine/` is EMPTY. The release is the
server's HTTP surface, the client and the docs. The codes live in memory and
are deliberately not persisted, so nothing new reaches the volume and there is
nothing to migrate. README, instructions.md and the release notes in all five
locales say so.

NOT YET EXERCISED END TO END: the two routes and the action are typechecked and
the claim store is unit-tested, but nothing has run them against a live server.
This build is what makes that possible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017nnuCv8UodHucFfx3LWEoX
2026-09-16 20:21:15 -04:00

84 lines
3.6 KiB
TypeScript

export const DEFAULT_LANG = 'en_US'
const dict = {
// main.ts
'Starting Station Master!': 0,
'Multiplayer Server': 1,
'The multiplayer server is ready': 2,
'The multiplayer server is not ready': 3,
// interfaces.ts
'Multiplayer Table': 4,
'Create or join a game, and play in the browser': 5,
// actions/getJoinSecret.ts
'Get Join Secret': 6,
'Retrieve or rotate the secret players need to create or join a game': 7,
// init/generateSecrets.ts
'Get the join secret to share with players': 8,
// main.ts — the health check's game counts
'Multiplayer server is ready': 9,
'no games in progress': 10,
'1 game in progress': 11,
'games in progress': 12,
'1 waiting to start': 13,
'waiting to start': 14,
// actions/gamesInProgress.ts, actions/manageGame.ts, serverApi.ts
'Games in Progress': 15,
'List every game and lobby on this server, and where each one has got to': 16,
'There are no games on this server.': 17,
'game(s) on this server. Use Manage Game to save one for later, or to end it.': 18,
'Waiting to start \u2014 nobody has played a turn yet.': 19,
Seats: 20,
Created: 21,
'Finished \u2014 this game is over and waits on nobody.': 22,
'Waiting on': 23,
seat: 24,
'nobody \u2014 the Mainline Phase is running itself': 25,
Players: 26,
Day: 27,
Stage: 28,
Started: 29,
'Last move': 30,
unknown: 31,
'Manage Game': 32,
'Save a game for later, or end one that will never finish': 33,
'Ending a game cannot be undone. Its save is returned, so it can still be replayed.': 34,
seats: 35,
players: 36,
'waiting on': 37,
'No games on this server': 38,
Game: 39,
'Which game to act on': 40,
'What to do': 41,
'Export changes nothing. Ending deletes the game from the server.': 42,
'Export \u2014 save a copy, leave the game running': 43,
'End the game \u2014 delete it from the server': 44,
'Game Saved': 45,
'This is the whole game \u2014 its seed and every move made in it. Save it as a .json file and open it in the replay viewer to watch the game back. The game itself is untouched and still running.': 46,
Save: 47,
'Game Ended': 48,
'The game': 49,
'deleted from the server, and anyone still connected to it has been disconnected. Its save is below: keep it if you want to watch the game back, because this is the only copy left.': 50,
'No admin secret is stored for this service, so its games cannot be managed.': 51,
'Could not reach the game server': 52,
'that game no longer exists': 53,
'the server answered': 54,
'Join Secret': 55,
"Share this with anyone you want to be able to create or join a game on this server. It doesn't identify a person or a seat, just who's allowed at the lobby door. Running this action again generates a new one and restarts the server with it; anyone already seated in a game keeps playing, but the old secret stops working for new games and joins.": 56,
// actions/restoreSeat.ts
'Restore a Seat': 57,
'Create a one-time link that puts a player back into their seat': 58,
'A restore link works once and expires in 30 minutes. Whoever opens it takes that seat — send it to the right person, not to a public channel.': 59,
Seat: 60,
'Which player to restore': 61,
'No seated players on this server': 62,
'Restore Link': 63,
'Send this to the player and have them open it in their own browser. It works once, expires in 30 minutes, and puts them back in their seat. It does not contain their session token.': 64,
} as const
/**
* Plumbing. DO NOT EDIT.
*/
export type I18nKey = keyof typeof dict
export type LangDict = Record<(typeof dict)[I18nKey], string>
export default dict