From 1d1b076672a74585f5957039fc29242ca5eb0441 Mon Sep 17 00:00:00 2001 From: VariableVince <24507472+VariableVince@users.noreply.github.com> Date: Tue, 3 Mar 2026 03:20:10 +0100 Subject: [PATCH] Rename/fix: change Bots to Tribes (#3290) ## Description: Resolves #3285. As discussed on Discord. However, in at least one instance "Tribes" feels a bit off: in Humans vs Nations, team "Tribes" feels as human too while they are just bots. This PR changes Bots to Tribes outwardly by - Changing default EN translation. - Changing (untranslated) alt text in PlayerPanel. - To change "Team Bot" into "Team Tribes" too in PlayerInfoOverlay and TeamStats (team leaderboard in-game), translate team names in there from now on too. - This way we also fix a bug where team names were not translated yet in there. To add to that fix, also translate team names in LobbyPlayerView in the same way. For this we re-use the existing getTranslatedPlayerTeamLabel function from GameLeftSideBar by moving it to Utils. - No translation key was present yet for Humans and Nations teams, so added those to now be used in PlayerInfoOverlay, LobbyPlayerView and TeamStats for completeness. - No internal code changes so nothing breaks. **BEFORE (showing old team name Bot and also that team names weren't translated yet in TeamStats)** ![No translation yet in TeamStats](https://github.com/user-attachments/assets/38f465bc-ef82-4474-806c-015bb640d233) ![No translation yet in TeamStats 2](https://github.com/user-attachments/assets/a4387f1e-0e80-491d-b57d-e52b3c616e2b) **AFTER** (translations in Dutch only shown as proof here, did not include nl.json in the PR) ![AFTER translated in TeamStats for Humans vs Nations as an example in NL json](https://github.com/user-attachments/assets/1a7dcf4e-4263-4d6b-a992-58cb08a4fa7b) ![AFTER Tribe as player type in PlayerInfoPanel](https://github.com/user-attachments/assets/6fd09686-320e-4fee-9c0d-397e581aa676) ![AFTER translated Team name PlayerInfoPanel as an example](https://github.com/user-attachments/assets/1b4bc684-9ef4-47a9-b91c-4ed5cda65e9e) ![AFTER Tribes in EN now that it is translated in TeamStats so fetched from EN json](https://github.com/user-attachments/assets/5ea6528b-7e3c-4c6e-abeb-2769fb0aedee) ![AFTER Instructions example of changed text ](https://github.com/user-attachments/assets/6c7a7ab7-1dea-4f11-bacf-3e2edcdb074b) ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: tryout33 --- resources/lang/en.json | 16 +++++++++------- src/client/Utils.ts | 8 ++++++++ src/client/components/LobbyPlayerView.ts | 6 ++++-- src/client/graphics/layers/GameLeftSidebar.ts | 16 +++++----------- .../graphics/layers/PlayerInfoOverlay.ts | 6 ++++-- src/client/graphics/layers/PlayerPanel.ts | 7 ++----- src/client/graphics/layers/TeamStats.ts | 18 +++++++++++------- 7 files changed, 43 insertions(+), 34 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index b9c5a79f3..8d41f9170 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -115,7 +115,7 @@ "ui_options": "Options", "ui_options_desc": "The following elements can be found inside:", "ui_playeroverlay": "Player info overlay", - "ui_playeroverlay_desc": "When you hover over a country, the Player info overlay is displayed under Options. It shows the type of player: Human, Nation (smart bot), or Bot. A Nation's attitude towards you, ranging from Hostile to Friendly. And defending troops, gold, plus the number of Warships and various buildings the player has.", + "ui_playeroverlay_desc": "When you hover over a country, the Player info overlay is displayed under Options. It shows the type of player: Human, Nation, or Tribe. A Nation's attitude towards you, ranging from Hostile to Friendly. And defending troops, gold, plus the number of Warships and various buildings the player has.", "ui_wilderness": "Wilderness", "option_pause": "Pause/Unpause the game - Only available in single player mode.", "option_timer": "Timer - Time passed since the start of the game.", @@ -137,7 +137,7 @@ "info_trade": "Use \"Stop trading\" to stop giving the player gold and receiving their gold via trade ships. If you both click \"Start trading\" it will start again.", "info_ally_panel": "Ally info panel", "info_ally_desc": "When you ally with a player, the following new icons become available:", - "ally_betray": "Betray your ally, ending the alliance, halting trade, and weakening your defense. Trading between you is paused for 5 minutes (or until you become allies again) and others may stop trading too. And unless the other player was a traitor themselves, you'll be marked a traitor for 30 seconds. During this time an icon will be above your name and you will have a 50% defense debuff. Bots are less likely to ally with you and players will think twice before doing so.", + "ally_betray": "Betray your ally, ending the alliance, halting trade, and weakening your defense. Trading between you is paused for 5 minutes (or until you become allies again) and others may stop trading too. And unless the other player was a traitor themselves, you'll be marked a traitor for 30 seconds. During this time an icon will be above your name and you will have a 50% defense debuff. Tribes are less likely to ally with you and players will think twice before doing so.", "ally_donate": "Donate some of your troops to your ally. Used when they're low on troops and are being attacked, or when they need that extra power to crush an enemy.", "ally_donate_gold": "Donate some of your gold to your ally. Used when they're low on gold and need it for buildings, or when your team member is saving for that MIRV.", "build_menu_title": "Build menu", @@ -184,7 +184,7 @@ "toggle_achievements": "Toggle achievements", "sign_in_for_achievements": "Sign in for achievements", "options_title": "Options", - "bots": "Bots: ", + "bots": "Tribes: ", "bots_disabled": "Disabled", "disable_nations": "Disable Nations", "instant_build": "Instant build", @@ -264,7 +264,7 @@ "conquest_gold": "Conquered player gold", "stolen_gold": "Stolen with warships", "num_of_conquests_humans": "Player kills", - "num_of_conquests_bots": "Bot kills", + "num_of_conquests_bots": "Tribe kills", "duration": "Duration", "survival_time": "Survival time", "war": "War", @@ -399,7 +399,7 @@ "team_count": "Number of Teams", "team_type": "Team Type", "options_title": "Options", - "bots": "Bots: ", + "bots": "Tribes: ", "bots_disabled": "Disabled", "player_immunity_duration": "PVP immunity duration (minutes)", "disable_nations": "Disable Nations", @@ -440,7 +440,9 @@ "yellow": "Yellow", "orange": "Orange", "green": "Green", - "bot": "Bot" + "bot": "Tribes", + "humans": "Humans", + "nations": "Nations" }, "game_starting_modal": { "title": "Game is Starting...", @@ -779,7 +781,7 @@ "player_type": { "player": "Player", "nation": "Nation", - "bot": "Bot" + "bot": "Tribe" }, "relation": { "hostile": "Hostile", diff --git a/src/client/Utils.ts b/src/client/Utils.ts index eceba18c9..92b106a38 100644 --- a/src/client/Utils.ts +++ b/src/client/Utils.ts @@ -6,6 +6,7 @@ import { MessageType, PublicGameModifiers, Quads, + Team, Trios, } from "../core/game/Game"; import { GameConfig } from "../core/Schemas"; @@ -408,6 +409,13 @@ export const translateText = ( } }; +export function getTranslatedPlayerTeamLabel(team: Team | null): string { + if (!team) return ""; + const translationKey = `team_colors.${team.toLowerCase()}`; + const translated = translateText(translationKey); + return translated === translationKey ? team : translated; +} + /** * Severity colors mapping for message types */ diff --git a/src/client/components/LobbyPlayerView.ts b/src/client/components/LobbyPlayerView.ts index 6429ffef7..d5b9c5259 100644 --- a/src/client/components/LobbyPlayerView.ts +++ b/src/client/components/LobbyPlayerView.ts @@ -18,7 +18,7 @@ import { assignTeamsLobbyPreview } from "../../core/game/TeamAssignment"; import { UserSettings } from "../../core/game/UserSettings"; import { ClientInfo, TeamCountConfig } from "../../core/Schemas"; import { createRandomName } from "../../core/Util"; -import { translateText } from "../Utils"; +import { getTranslatedPlayerTeamLabel, translateText } from "../Utils"; export interface TeamPreviewData { team: Team; @@ -193,6 +193,8 @@ export class LobbyTeamView extends LitElement { ? effectiveNationCount : this.teamMaxSize; + const teamLabel = getTranslatedPlayerTeamLabel(preview.team); + return html`
` : null} - ${preview.team} + ${teamLabel} ${displayCount}/${maxTeamSize}
diff --git a/src/client/graphics/layers/GameLeftSidebar.ts b/src/client/graphics/layers/GameLeftSidebar.ts index 35dfb6328..16caeef3b 100644 --- a/src/client/graphics/layers/GameLeftSidebar.ts +++ b/src/client/graphics/layers/GameLeftSidebar.ts @@ -2,10 +2,10 @@ import { Colord } from "colord"; import { html, LitElement } from "lit"; import { customElement, state } from "lit/decorators.js"; import { EventBus } from "../../../core/EventBus"; -import { GameMode } from "../../../core/game/Game"; +import { GameMode, Team } from "../../../core/game/Game"; import { GameView } from "../../../core/game/GameView"; import { Platform } from "../../Platform"; -import { translateText } from "../../Utils"; +import { getTranslatedPlayerTeamLabel, translateText } from "../../Utils"; import { ImmunityBarVisibleEvent } from "./ImmunityTimer"; import { Layer } from "./Layer"; import { SpawnBarVisibleEvent } from "./SpawnTimer"; @@ -25,7 +25,7 @@ export class GameLeftSidebar extends LitElement implements Layer { @state() private isPlayerTeamLabelVisible = false; @state() - private playerTeam: string | null = null; + private playerTeam: Team | null = null; @state() private spawnBarVisible = false; @state() @@ -99,13 +99,6 @@ export class GameLeftSidebar extends LitElement implements Layer { return this.game?.config().gameConfig().gameMode === GameMode.Team; } - private getTranslatedPlayerTeamLabel(): string { - if (!this.playerTeam) return ""; - const translationKey = `team_colors.${this.playerTeam.toLowerCase()}`; - const translated = translateText(translationKey); - return translated === translationKey ? this.playerTeam : translated; - } - render() { return html`
` diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts index 22d3b341a..c3c6cbe55 100644 --- a/src/client/graphics/layers/PlayerInfoOverlay.ts +++ b/src/client/graphics/layers/PlayerInfoOverlay.ts @@ -19,6 +19,7 @@ import { TouchEvent, } from "../../InputHandler"; import { + getTranslatedPlayerTeamLabel, renderDuration, renderNumber, renderTroops, @@ -314,6 +315,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer { playerType = translateText("player_type.player"); break; } + const playerTeam = getTranslatedPlayerTeamLabel(player.team()); return html`
@@ -357,7 +359,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer { />` : html``} ${player.name()} - ${player.team() !== null && player.type() !== PlayerType.Bot + ${playerTeam !== "" && player.type() !== PlayerType.Bot ? html`
${playerType}${player.team()}${playerTeam}]
` diff --git a/src/client/graphics/layers/PlayerPanel.ts b/src/client/graphics/layers/PlayerPanel.ts index d3b1ac584..1b759577b 100644 --- a/src/client/graphics/layers/PlayerPanel.ts +++ b/src/client/graphics/layers/PlayerPanel.ts @@ -340,22 +340,19 @@ export class PlayerPanel extends LitElement implements Layer { case PlayerType.Nation: return { labelKey: "player_type.nation", - aria: "Nation player", classes: "border-indigo-400/25 bg-indigo-500/10 text-indigo-200", icon: "🏛️", }; case PlayerType.Bot: return { labelKey: "player_type.bot", - aria: "Bot", classes: "border-purple-400/25 bg-purple-500/10 text-purple-200", - icon: "🤖", + icon: "⚔️", }; case PlayerType.Human: default: return { labelKey: "player_type.player", - aria: "Human player", classes: "border-zinc-400/20 bg-zinc-500/5 text-zinc-300", icon: "👤", }; @@ -517,7 +514,7 @@ export class PlayerPanel extends LitElement implements Layer { ? html` diff --git a/src/client/graphics/layers/TeamStats.ts b/src/client/graphics/layers/TeamStats.ts index 5878c5aab..6e846bcdf 100644 --- a/src/client/graphics/layers/TeamStats.ts +++ b/src/client/graphics/layers/TeamStats.ts @@ -69,14 +69,18 @@ export class TeamStats extends LitElement implements Layer { } for (const player of players) { - const team = player.team(); - if (team === null) continue; - grouped[team] ??= []; - grouped[team].push(player); + const rawTeam = player.team(); + if (rawTeam === null) continue; + grouped[rawTeam] ??= []; + grouped[rawTeam].push(player); } this.teams = Object.entries(grouped) - .map(([teamStr, teamPlayers]) => { + .map(([rawTeam, teamPlayers]) => { + const key = `team_colors.${rawTeam.toLowerCase()}`; + const translated = translateText(key); + const teamName = translated !== key ? translated : rawTeam; + let totalGold = 0n; let totalMaxTroops = 0; let totalScoreSort = 0; @@ -102,8 +106,8 @@ export class TeamStats extends LitElement implements Layer { const totalScorePercent = totalScoreSort / numTilesWithoutFallout; return { - teamName: teamStr, - isMyTeam: teamStr === this._myTeam, + teamName, + isMyTeam: rawTeam === this._myTeam, totalScoreStr: formatPercentage(totalScorePercent), totalScoreSort, totalGold: renderNumber(totalGold),