54733bfb14
Send joins Modernize / Dismantle / Transfer as a lockable command: once any of the four lands in the draft for a group, every action button on its inspector is disabled with a "command pending" tooltip and the banner names the queued kind. Load / Unload / Split / Join Fleet stay non-locking — they stack legitimately on the engine side. Two dashed overlays now run alongside the cargo-route arrows: - Yellow dashed track for own in-space groups, drawn from the origin planet to the destination (matches the in-space point colour so eye reads both as one entity). - Green dashed track for every wire-valid sendShipGroup command in the order draft, drawn from the source group's orbit planet to the chosen destination. Disappears when the command is removed from the order tab, when the engine rejects it, or when the group has left orbit (in-space track replaces it). Both tracks are wrap-aware via torusShortestDelta and never participate in hit-test. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
348 lines
20 KiB
TypeScript
348 lines
20 KiB
TypeScript
// English translation dictionary. Keys are dotted strings grouped
|
||
// by feature area (`login.*`, `lobby.*`, `common.*`); values are
|
||
// the user-visible text. Adding a new key here also requires adding
|
||
// it to every other locale dictionary in this folder, otherwise the
|
||
// `t()` helper falls back to English at runtime.
|
||
|
||
const en = {
|
||
"common.language": "language",
|
||
"common.loading": "loading…",
|
||
"common.browser_not_supported_title": "browser not supported",
|
||
"common.browser_not_supported_body":
|
||
"Galaxy requires Ed25519 in WebCrypto. See supported browsers.",
|
||
|
||
"login.title": "sign in to Galaxy",
|
||
"login.email_label": "email",
|
||
"login.email_required": "email must not be empty",
|
||
"login.send_code": "send code",
|
||
"login.sending": "sending…",
|
||
"login.code_label": "code",
|
||
"login.code_required": "code must not be empty",
|
||
"login.code_sent_to": "code sent to {email}",
|
||
"login.verify": "verify",
|
||
"login.verifying": "verifying…",
|
||
"login.send_new_code": "send a new code",
|
||
"login.change_email": "change email",
|
||
"login.challenge_expired":
|
||
"challenge expired, please request a new code",
|
||
"login.code_expired_or_used":
|
||
"code expired or already used, please request a new one",
|
||
"login.device_key_not_ready":
|
||
"device key is not ready, please reload the page",
|
||
|
||
"lobby.title": "you are logged in",
|
||
"lobby.device_session_id_label": "device session id",
|
||
"lobby.greeting": "hello, {name}!",
|
||
"lobby.account_loading": "loading account…",
|
||
"lobby.logout": "logout",
|
||
"lobby.section.my_games": "my games",
|
||
"lobby.section.invitations": "pending invitations",
|
||
"lobby.section.applications": "my applications",
|
||
"lobby.section.public_games": "public games",
|
||
"lobby.section.create": "create a game",
|
||
"lobby.create_button": "create new game",
|
||
"lobby.my_games.empty": "no games yet",
|
||
"lobby.invitations.empty": "no invitations",
|
||
"lobby.applications.empty": "no applications",
|
||
"lobby.public_games.empty": "no public games",
|
||
"lobby.invitation.accept": "accept",
|
||
"lobby.invitation.decline": "decline",
|
||
"lobby.application.submit": "submit application",
|
||
"lobby.application.submit_for": "join {name}",
|
||
"lobby.application.race_name_label": "race name",
|
||
"lobby.application.race_name_required": "race name must not be empty",
|
||
"lobby.application.cancel": "cancel",
|
||
"lobby.application.submitted": "application submitted, awaiting approval",
|
||
"lobby.application.status.pending": "pending",
|
||
"lobby.application.status.approved": "approved",
|
||
"lobby.application.status.rejected": "rejected",
|
||
"lobby.application.status.unknown": "{status}",
|
||
"lobby.list_loading": "loading…",
|
||
"lobby.create.title": "create new game",
|
||
"lobby.create.game_name_label": "game name",
|
||
"lobby.create.description_label": "description",
|
||
"lobby.create.turn_schedule_label": "turn schedule",
|
||
"lobby.create.turn_schedule_hint": "five-field cron, e.g. 0 0 * * *",
|
||
"lobby.create.enrollment_ends_at_label": "enrollment ends at",
|
||
"lobby.create.advanced": "advanced",
|
||
"lobby.create.min_players_label": "min players",
|
||
"lobby.create.max_players_label": "max players",
|
||
"lobby.create.start_gap_hours_label": "start gap (hours)",
|
||
"lobby.create.start_gap_players_label": "start gap (players)",
|
||
"lobby.create.target_engine_version_label": "target engine version",
|
||
"lobby.create.submit": "create",
|
||
"lobby.create.submitting": "creating…",
|
||
"lobby.create.cancel": "cancel",
|
||
"lobby.create.game_name_required": "game name must not be empty",
|
||
"lobby.create.turn_schedule_required": "turn schedule must not be empty",
|
||
"lobby.create.enrollment_ends_at_required": "enrollment end time must be set",
|
||
"lobby.error.invalid_request": "request is invalid",
|
||
"lobby.error.subject_not_found": "not found",
|
||
"lobby.error.forbidden": "operation is forbidden",
|
||
"lobby.error.conflict": "request conflicts with current state",
|
||
"lobby.error.internal_error": "internal server error",
|
||
"lobby.error.unknown": "{message}",
|
||
|
||
"game.shell.unknown": "?",
|
||
"game.shell.headline": "{race} @ {game}, turn {turn}",
|
||
"game.shell.connection.online": "online",
|
||
"game.shell.connection.reconnecting": "reconnecting…",
|
||
"game.shell.connection.offline": "offline",
|
||
"game.shell.menu.toggle_sidebar": "open sidebar",
|
||
"game.shell.menu.close_sidebar": "close sidebar",
|
||
"game.shell.menu.open_views": "open views menu",
|
||
"game.shell.menu.close_views": "close views menu",
|
||
"game.shell.menu.account": "account",
|
||
"game.shell.menu.settings": "settings",
|
||
"game.shell.menu.sessions": "sessions",
|
||
"game.shell.menu.theme": "theme",
|
||
"game.shell.menu.language": "language",
|
||
"game.shell.menu.logout": "logout",
|
||
"game.shell.coming_soon": "coming soon",
|
||
"game.view.map": "map",
|
||
"game.view.table": "table",
|
||
"game.view.table.planets": "planets",
|
||
"game.view.table.ship_classes": "ship classes",
|
||
"game.view.table.ship_groups": "ship groups",
|
||
"game.view.table.fleets": "fleets",
|
||
"game.view.table.sciences": "sciences",
|
||
"game.view.table.races": "races",
|
||
"game.view.report": "turn report",
|
||
"game.view.battle": "battle log",
|
||
"game.view.mail": "diplomatic mail",
|
||
"game.view.designer.ship_class": "ship-class designer",
|
||
"game.view.designer.science": "science designer",
|
||
"game.sidebar.tab.calculator": "calculator",
|
||
"game.sidebar.tab.inspector": "inspector",
|
||
"game.sidebar.tab.order": "order",
|
||
"game.sidebar.empty.calculator": "coming soon",
|
||
"game.sidebar.empty.inspector": "select an object on the map",
|
||
"game.sidebar.empty.order": "order is empty",
|
||
"game.sidebar.order.command_delete": "delete",
|
||
"game.sidebar.order.sync.idle": "no changes yet",
|
||
"game.sidebar.order.sync.in_flight": "syncing…",
|
||
"game.sidebar.order.sync.synced": "synced with server",
|
||
"game.sidebar.order.sync.error": "sync failed: {message}",
|
||
"game.sidebar.order.sync.retry": "retry",
|
||
"game.sidebar.order.status.draft": "draft",
|
||
"game.sidebar.order.status.valid": "valid",
|
||
"game.sidebar.order.status.invalid": "invalid",
|
||
"game.sidebar.order.status.submitting": "submitting",
|
||
"game.sidebar.order.status.applied": "applied",
|
||
"game.sidebar.order.status.rejected": "rejected",
|
||
"game.sidebar.order.label.placeholder": "{label}",
|
||
"game.sidebar.order.label.planet_rename": "rename planet {planet} → {name}",
|
||
"game.sidebar.order.label.planet_production": "set production on planet {planet} → {target}",
|
||
"game.bottom_tabs.map": "map",
|
||
"game.bottom_tabs.calc": "calc",
|
||
"game.bottom_tabs.order": "order",
|
||
"game.bottom_tabs.more": "more",
|
||
|
||
"game.inspector.planet.kind.local": "your planet",
|
||
"game.inspector.planet.kind.other": "other race planet",
|
||
"game.inspector.planet.kind.uninhabited": "uninhabited planet",
|
||
"game.inspector.planet.kind.unidentified": "unidentified planet",
|
||
"game.inspector.planet.field.name": "name",
|
||
"game.inspector.planet.field.owner": "owner",
|
||
"game.inspector.planet.field.coordinates": "coordinates",
|
||
"game.inspector.planet.field.size": "size",
|
||
"game.inspector.planet.field.population": "population",
|
||
"game.inspector.planet.field.colonists": "colonists",
|
||
"game.inspector.planet.field.industry": "industry",
|
||
"game.inspector.planet.field.industry_stockpile": "industry stockpile ($)",
|
||
"game.inspector.planet.field.materials_stockpile": "materials stockpile (M)",
|
||
"game.inspector.planet.field.natural_resources": "natural resources",
|
||
"game.inspector.planet.field.production": "current production",
|
||
"game.inspector.planet.field.free_industry": "free production",
|
||
"game.inspector.planet.production_none": "none",
|
||
"game.inspector.planet.unidentified_no_data": "no data — only the location is known",
|
||
"game.inspector.sheet_close": "close",
|
||
"game.inspector.planet.action.rename": "rename",
|
||
"game.inspector.planet.rename.title": "rename planet",
|
||
"game.inspector.planet.rename.confirm": "save",
|
||
"game.inspector.planet.rename.cancel": "cancel",
|
||
"game.inspector.planet.rename.invalid.empty": "name cannot be empty",
|
||
"game.inspector.planet.rename.invalid.too_long": "name is too long (30 characters max)",
|
||
"game.inspector.planet.rename.invalid.starts_with_special": "name cannot start with a special character",
|
||
"game.inspector.planet.rename.invalid.ends_with_special": "name cannot end with a special character",
|
||
"game.inspector.planet.rename.invalid.consecutive_specials": "too many special characters in a row",
|
||
"game.inspector.planet.rename.invalid.whitespace": "name cannot contain spaces",
|
||
"game.inspector.planet.rename.invalid.disallowed_character": "name contains disallowed characters",
|
||
"game.inspector.planet.production.title": "production",
|
||
"game.inspector.planet.production.option.industry": "industry",
|
||
"game.inspector.planet.production.option.materials": "materials",
|
||
"game.inspector.planet.production.option.research": "research",
|
||
"game.inspector.planet.production.option.ship": "build ship",
|
||
"game.inspector.planet.production.research.drive": "drive",
|
||
"game.inspector.planet.production.research.weapons": "weapons",
|
||
"game.inspector.planet.production.research.shields": "shields",
|
||
"game.inspector.planet.production.research.cargo": "cargo",
|
||
"game.inspector.planet.production.ship.no_classes": "no ship classes designed yet",
|
||
"game.inspector.planet.cargo.title": "cargo routes",
|
||
"game.inspector.planet.cargo.slot.col": "colonists",
|
||
"game.inspector.planet.cargo.slot.cap": "industry",
|
||
"game.inspector.planet.cargo.slot.mat": "materials",
|
||
"game.inspector.planet.cargo.slot.emp": "empty ships",
|
||
"game.inspector.planet.cargo.empty": "(no route)",
|
||
"game.inspector.planet.cargo.add": "add",
|
||
"game.inspector.planet.cargo.edit": "edit",
|
||
"game.inspector.planet.cargo.remove": "remove",
|
||
"game.inspector.planet.cargo.pick.prompt": "pick a destination on the map (Esc to cancel)",
|
||
"game.inspector.planet.cargo.pick.cancel": "cancel pick",
|
||
"game.inspector.planet.cargo.pick.no_destinations": "no reachable destinations within {reach} world units",
|
||
"game.sidebar.order.label.cargo_route_set": "set {loadType} route from planet {source} → planet {destination}",
|
||
"game.sidebar.order.label.cargo_route_remove": "remove {loadType} route from planet {source}",
|
||
"game.sidebar.order.label.ship_class_create": "design ship class {name}",
|
||
"game.sidebar.order.label.ship_class_remove": "remove ship class {name}",
|
||
"game.sidebar.order.label.ship_group_break": "split group {group} → {quantity} ships into new group",
|
||
"game.sidebar.order.label.ship_group_send": "send group {group} → planet {destination}",
|
||
"game.sidebar.order.label.ship_group_load": "load {cargo} × {quantity} onto group {group}",
|
||
"game.sidebar.order.label.ship_group_unload": "unload × {quantity} from group {group}",
|
||
"game.sidebar.order.label.ship_group_upgrade": "modernize group {group} {tech} → {level}",
|
||
"game.sidebar.order.label.ship_group_dismantle": "dismantle group {group}",
|
||
"game.sidebar.order.label.ship_group_transfer": "transfer group {group} → {acceptor}",
|
||
"game.sidebar.order.label.ship_group_join_fleet": "assign group {group} → fleet {fleet}",
|
||
"game.table.ship_classes.title": "ship classes",
|
||
"game.table.ship_classes.column.name": "name",
|
||
"game.table.ship_classes.column.drive": "drive",
|
||
"game.table.ship_classes.column.armament": "armament",
|
||
"game.table.ship_classes.column.weapons": "weapons",
|
||
"game.table.ship_classes.column.shields": "shields",
|
||
"game.table.ship_classes.column.cargo": "cargo",
|
||
"game.table.ship_classes.column.actions": "actions",
|
||
"game.table.ship_classes.empty": "no ship classes designed yet",
|
||
"game.table.ship_classes.filter.placeholder": "filter by name",
|
||
"game.table.ship_classes.action.new": "+ new ship class",
|
||
"game.table.ship_classes.action.delete": "delete",
|
||
"game.table.ship_classes.loading": "loading ship classes…",
|
||
"game.designer.ship_class.title.new": "design new ship class",
|
||
"game.designer.ship_class.title.view": "ship class {name}",
|
||
"game.designer.ship_class.field.name": "name",
|
||
"game.designer.ship_class.field.drive": "drive",
|
||
"game.designer.ship_class.field.armament": "armament",
|
||
"game.designer.ship_class.field.weapons": "weapons",
|
||
"game.designer.ship_class.field.shields": "shields",
|
||
"game.designer.ship_class.field.cargo": "cargo",
|
||
"game.designer.ship_class.action.save": "save",
|
||
"game.designer.ship_class.action.cancel": "cancel",
|
||
"game.designer.ship_class.action.delete": "delete",
|
||
"game.designer.ship_class.action.back": "back",
|
||
"game.designer.ship_class.hint.values": "each value is either 0 or ≥ 1; armament is a non-negative integer; armament and weapons are both zero or both nonzero",
|
||
"game.designer.ship_class.read_only_notice": "ship classes are designed once; values cannot be edited after creation",
|
||
"game.designer.ship_class.not_found": "ship class \"{name}\" does not exist",
|
||
"game.designer.ship_class.invalid.empty": "name cannot be empty",
|
||
"game.designer.ship_class.invalid.too_long": "name is too long (30 characters max)",
|
||
"game.designer.ship_class.invalid.starts_with_special": "name cannot start with a special character",
|
||
"game.designer.ship_class.invalid.ends_with_special": "name cannot end with a special character",
|
||
"game.designer.ship_class.invalid.consecutive_specials": "too many special characters in a row",
|
||
"game.designer.ship_class.invalid.whitespace": "name cannot contain spaces",
|
||
"game.designer.ship_class.invalid.disallowed_character": "name contains disallowed characters",
|
||
"game.designer.ship_class.invalid.duplicate_name": "a ship class with this name already exists",
|
||
"game.designer.ship_class.invalid.drive_value": "drive must be 0 or ≥ 1",
|
||
"game.designer.ship_class.invalid.armament_value": "armament must be 0 or a positive integer",
|
||
"game.designer.ship_class.invalid.armament_not_integer": "armament must be an integer",
|
||
"game.designer.ship_class.invalid.weapons_value": "weapons must be 0 or ≥ 1",
|
||
"game.designer.ship_class.invalid.shields_value": "shields must be 0 or ≥ 1",
|
||
"game.designer.ship_class.invalid.cargo_value": "cargo must be 0 or ≥ 1",
|
||
"game.designer.ship_class.invalid.armament_weapons_pair": "armament and weapons must be both zero or both nonzero",
|
||
"game.designer.ship_class.invalid.all_zero": "at least one value must be nonzero",
|
||
"game.designer.ship_class.preview.title": "preview at your tech levels",
|
||
"game.designer.ship_class.preview.mass": "mass",
|
||
"game.designer.ship_class.preview.full_load_mass": "full-load mass",
|
||
"game.designer.ship_class.preview.max_speed": "max speed (ly/turn)",
|
||
"game.designer.ship_class.preview.range": "range at full load (ly/turn)",
|
||
"game.designer.ship_class.preview.cargo_capacity": "cargo capacity per ship",
|
||
"game.designer.ship_class.preview.unavailable": "—",
|
||
|
||
"game.inspector.ship_group.kind.local": "your group",
|
||
"game.inspector.ship_group.kind.other": "other race group",
|
||
"game.inspector.ship_group.kind.incoming": "incoming group",
|
||
"game.inspector.ship_group.kind.unidentified": "unidentified group",
|
||
"game.inspector.ship_group.field.class": "class",
|
||
"game.inspector.ship_group.field.count": "ships",
|
||
"game.inspector.ship_group.field.drive": "drive",
|
||
"game.inspector.ship_group.field.weapons": "weapons",
|
||
"game.inspector.ship_group.field.shields": "shields",
|
||
"game.inspector.ship_group.field.cargo_tech": "cargo",
|
||
"game.inspector.ship_group.field.mass": "mass",
|
||
"game.inspector.ship_group.field.cargo_load": "cargo aboard",
|
||
"game.inspector.ship_group.field.location": "location",
|
||
"game.inspector.ship_group.field.from": "from",
|
||
"game.inspector.ship_group.field.to": "to",
|
||
"game.inspector.ship_group.field.distance": "distance remaining",
|
||
"game.inspector.ship_group.field.speed": "speed (ly/turn)",
|
||
"game.inspector.ship_group.field.eta": "ETA (turns)",
|
||
"game.inspector.ship_group.field.fleet": "fleet",
|
||
"game.inspector.ship_group.field.state": "state",
|
||
"game.inspector.ship_group.field.coordinates": "coordinates",
|
||
"game.inspector.ship_group.cargo.col": "colonists",
|
||
"game.inspector.ship_group.cargo.cap": "industry",
|
||
"game.inspector.ship_group.cargo.mat": "materials",
|
||
"game.inspector.ship_group.cargo.emp": "empty",
|
||
"game.inspector.ship_group.cargo.none": "none",
|
||
"game.inspector.ship_group.location.in_hyperspace": "in hyperspace",
|
||
"game.inspector.ship_group.fleet.none": "—",
|
||
"game.inspector.ship_group.unidentified_no_data": "no data — only the radar blip is known",
|
||
|
||
"game.inspector.ship_group.action.split": "split",
|
||
"game.inspector.ship_group.action.send": "send",
|
||
"game.inspector.ship_group.action.load": "load",
|
||
"game.inspector.ship_group.action.unload": "unload",
|
||
"game.inspector.ship_group.action.modernize": "modernize",
|
||
"game.inspector.ship_group.action.dismantle": "dismantle",
|
||
"game.inspector.ship_group.action.transfer": "transfer",
|
||
"game.inspector.ship_group.action.join_fleet": "join fleet",
|
||
"game.inspector.ship_group.action.confirm": "confirm",
|
||
"game.inspector.ship_group.action.cancel": "cancel",
|
||
"game.inspector.ship_group.action.confirm_destroy": "confirm — colonists die",
|
||
"game.inspector.ship_group.action.disabled.not_in_orbit": "ships are busy ({state}); only orbiting groups accept actions",
|
||
"game.inspector.ship_group.action.disabled.no_reach": "no planets are within drive range",
|
||
"game.inspector.ship_group.action.disabled.no_drive": "this ship class has no drive block",
|
||
"game.inspector.ship_group.action.disabled.no_cargo_block": "this ship class has no cargo block",
|
||
"game.inspector.ship_group.action.disabled.no_planet": "the orbit planet is not visible",
|
||
"game.inspector.ship_group.action.disabled.foreign_planet": "this action is only available on your own or unowned planets",
|
||
"game.inspector.ship_group.action.disabled.empty_cargo": "the group is empty",
|
||
"game.inspector.ship_group.action.disabled.foreign_unload_col": "colonists cannot be unloaded over a foreign planet",
|
||
"game.inspector.ship_group.action.disabled.no_headroom": "the group's tech is already at your race level",
|
||
"game.inspector.ship_group.action.disabled.no_planet_stock": "the planet has no available stock of this cargo",
|
||
"game.inspector.ship_group.action.disabled.full_load": "the group is fully loaded",
|
||
"game.inspector.ship_group.action.disabled.no_other_races": "no other non-extinct races to transfer to",
|
||
"game.inspector.ship_group.action.disabled.unknown_class": "the ship class is missing from the report",
|
||
"game.inspector.ship_group.action.disabled.locked": "an order is already queued for this group; cancel it in the order list to issue a new one",
|
||
"game.inspector.ship_group.action.locked.banner": "an order is already queued for this group: {command}. Cancel it in the order list to issue another action.",
|
||
"game.inspector.ship_group.action.locked.kind.send": "send",
|
||
"game.inspector.ship_group.action.locked.kind.modernize": "modernize",
|
||
"game.inspector.ship_group.action.locked.kind.dismantle": "dismantle",
|
||
"game.inspector.ship_group.action.locked.kind.transfer": "transfer",
|
||
"game.inspector.ship_group.action.field.ships": "ships ({max} total)",
|
||
"game.inspector.ship_group.action.field.cargo": "cargo type",
|
||
"game.inspector.ship_group.action.field.quantity": "quantity",
|
||
"game.inspector.ship_group.action.field.level": "tech level",
|
||
"game.inspector.ship_group.action.field.tech": "tech",
|
||
"game.inspector.ship_group.action.field.acceptor": "acceptor",
|
||
"game.inspector.ship_group.action.field.fleet": "fleet name",
|
||
"game.inspector.ship_group.action.field.destination": "destination planet",
|
||
"game.inspector.ship_group.action.tech.all": "all blocks",
|
||
"game.inspector.ship_group.action.tech.drive": "drive",
|
||
"game.inspector.ship_group.action.tech.weapons": "weapons",
|
||
"game.inspector.ship_group.action.tech.shields": "shields",
|
||
"game.inspector.ship_group.action.tech.cargo": "cargo",
|
||
"game.inspector.ship_group.action.send.pick_prompt": "click a planet on the map (Esc to cancel)",
|
||
"game.inspector.ship_group.action.modernize.cost": "estimated cost: {cost}",
|
||
"game.inspector.ship_group.action.modernize.cost_unavailable": "cost preview unavailable",
|
||
"game.inspector.ship_group.action.dismantle.warning": "the group is over a foreign planet with colonists aboard — they will die",
|
||
"game.inspector.ship_group.action.fleet.create_new": "+ new fleet",
|
||
"game.inspector.ship_group.action.invalid.ship_count": "ships must be in the range 1…{max}",
|
||
"game.inspector.ship_group.action.invalid.quantity": "quantity must be greater than zero",
|
||
"game.inspector.ship_group.action.invalid.level": "level must be in ({current}, {max}]",
|
||
"game.inspector.ship_group.action.invalid.fleet_name": "fleet name does not match the entity-name rules",
|
||
|
||
"game.inspector.planet.ship_groups.title": "stationed ship groups",
|
||
"game.inspector.planet.ship_groups.row.count": "{count} ships",
|
||
"game.inspector.planet.ship_groups.row.mass": "mass {mass}",
|
||
"game.inspector.planet.ship_groups.race.unknown": "unknown",
|
||
"game.inspector.planet.ship_groups.race.foreign": "foreign",
|
||
} as const;
|
||
|
||
export default en;
|