From 0b67b5bfaea9d65ca0114b8e63bbf761759c504e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Mon, 29 Aug 2022 20:56:25 +0200 Subject: [PATCH] Extract translation strings. --- OpenRA.Game/Server/PlayerMessageTracker.cs | 6 +- OpenRA.Game/Server/Server.cs | 9 +- .../LoadScreens/BlankLoadScreen.cs | 2 +- .../ServerTraits/LobbyCommands.cs | 4 +- .../Widgets/ConfirmationDialogs.cs | 48 +- .../Widgets/Logic/AssetBrowserLogic.cs | 16 +- .../Widgets/Logic/ConnectionLogic.cs | 34 +- .../Logic/Editor/CommonSelectorLogic.cs | 13 +- .../Widgets/Logic/Editor/SaveMapLogic.cs | 56 ++- .../Widgets/Logic/GameSaveBrowserLogic.cs | 76 ++- .../Logic/Ingame/GameInfoStatsLogic.cs | 53 ++- .../Widgets/Logic/Ingame/IngameChatLogic.cs | 12 +- .../Widgets/Logic/Ingame/IngameMenuLogic.cs | 168 +++++-- .../Ingame/ObserverShroudSelectorLogic.cs | 10 +- .../Logic/Ingame/ObserverStatsLogic.cs | 14 +- .../Installation/DownloadPackageLogic.cs | 62 ++- .../Installation/InstallFromDiscLogic.cs | 113 +++-- .../Logic/Installation/ModContentLogic.cs | 12 +- .../Installation/ModContentPromptLogic.cs | 13 +- .../Widgets/Logic/IntroductionPromptLogic.cs | 19 +- .../Widgets/Logic/Lobby/KickClientLogic.cs | 8 +- .../Logic/Lobby/KickSpectatorsLogic.cs | 8 +- .../Widgets/Logic/Lobby/LobbyLogic.cs | 70 ++- .../Widgets/Logic/Lobby/LobbyOptionsLogic.cs | 9 +- .../Widgets/Logic/Lobby/LobbyUtils.cs | 41 +- .../Widgets/Logic/Lobby/MapPreviewLogic.cs | 42 +- .../Logic/Lobby/SpawnSelectorTooltipLogic.cs | 23 +- .../Widgets/Logic/MainMenuLogic.cs | 18 +- .../Widgets/Logic/MapChooserLogic.cs | 87 +++- .../Widgets/Logic/MissionBrowserLogic.cs | 34 +- .../Widgets/Logic/MusicPlayerLogic.cs | 13 +- .../Widgets/Logic/MuteHotkeyLogic.cs | 17 +- .../Widgets/Logic/PlayerProfileLogic.cs | 10 +- .../Widgets/Logic/ReplayBrowserLogic.cs | 129 ++++-- .../Widgets/Logic/ReplayUtils.cs | 46 +- .../Widgets/Logic/ServerCreationLogic.cs | 56 ++- .../Widgets/Logic/ServerListLogic.cs | 153 ++++-- .../Logic/Settings/DisplaySettingsLogic.cs | 141 ++++-- .../Logic/Settings/InputSettingsLogic.cs | 80 +++- .../Widgets/Logic/Settings/SettingsLogic.cs | 64 ++- mods/common/languages/en.ftl | 437 +++++++++++++++++- mods/modcontent/mod.yaml | 3 + 42 files changed, 1819 insertions(+), 410 deletions(-) diff --git a/OpenRA.Game/Server/PlayerMessageTracker.cs b/OpenRA.Game/Server/PlayerMessageTracker.cs index 33c802394a..4fcb39f79f 100644 --- a/OpenRA.Game/Server/PlayerMessageTracker.cs +++ b/OpenRA.Game/Server/PlayerMessageTracker.cs @@ -17,7 +17,7 @@ namespace OpenRA.Server class PlayerMessageTracker { [TranslationReference("remaining")] - static readonly string ChatDisabled = "chat-disabled"; + static readonly string ChatTemporaryDisabled = "chat-temp-disabled"; readonly Dictionary> messageTracker = new Dictionary>(); readonly Server server; @@ -56,7 +56,7 @@ namespace OpenRA.Server if (!isAdmin && time < settings.FloodLimitJoinCooldown) { var remaining = CalculateRemaining(settings.FloodLimitJoinCooldown); - sendLocalizedMessageTo(conn, ChatDisabled, Translation.Arguments("remaining", remaining)); + sendLocalizedMessageTo(conn, ChatTemporaryDisabled, Translation.Arguments("remaining", remaining)); return true; } @@ -64,7 +64,7 @@ namespace OpenRA.Server if (tracker.Count >= settings.FloodLimitMessageCount) { var remaining = CalculateRemaining(tracker[0] + settings.FloodLimitInterval); - sendLocalizedMessageTo(conn, ChatDisabled, Translation.Arguments("remaining", remaining)); + sendLocalizedMessageTo(conn, ChatTemporaryDisabled, Translation.Arguments("remaining", remaining)); return true; } diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 81e00f9fd5..24550c7dc7 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -132,9 +132,12 @@ namespace OpenRA.Server [TranslationReference("player")] static readonly string LobbyDisconnected = "lobby-disconnected"; - [TranslationReference("player", "team")] + [TranslationReference("player")] static readonly string PlayerDisconnected = "player-disconnected"; + [TranslationReference("player", "team")] + static readonly string PlayerTeamDisconnected = "player-team-disconnected"; + [TranslationReference("player")] static readonly string ObserverDisconnected = "observer-disconnected"; @@ -1178,8 +1181,10 @@ namespace OpenRA.Server { if (dropClient.IsObserver) SendLocalizedMessage(ObserverDisconnected, Translation.Arguments("player", dropClient.Name)); + else if (dropClient.Team > 0) + SendLocalizedMessage(PlayerTeamDisconnected, Translation.Arguments("player", dropClient.Name, "team", dropClient.Team)); else - SendLocalizedMessage(PlayerDisconnected, Translation.Arguments("player", dropClient.Name, "team", dropClient.Team)); + SendLocalizedMessage(PlayerDisconnected, Translation.Arguments("player", dropClient.Name)); } else SendLocalizedMessage(LobbyDisconnected, Translation.Arguments("player", dropClient.Name)); diff --git a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs index ca715bbf48..0d4db067ed 100644 --- a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs @@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.LoadScreens } catch { } - if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.LoadShellMap)) + if (ReplayUtils.PromptConfirmReplayCompatibility(replayMeta, Game.ModData, Game.LoadShellMap)) Game.JoinReplay(Launch.Replay); if (replayMeta != null) diff --git a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs index b2ea4305ea..e813ad0b6c 100644 --- a/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs +++ b/OpenRA.Mods.Common/ServerTraits/LobbyCommands.cs @@ -785,14 +785,14 @@ namespace OpenRA.Mods.Common.Server } Log.Write("server", $"Kicking client {kickClientID}."); - server.SendLocalizedMessage(Kicked, Translation.Arguments("admin", client.Name, "client", kickClient.Name)); + server.SendLocalizedMessage(Kicked, Translation.Arguments("admin", client.Name, "player", kickClient.Name)); server.SendOrderTo(kickConn, "ServerError", YouWereKicked); server.DropClient(kickConn); if (bool.TryParse(split[1], out var tempBan) && tempBan) { Log.Write("server", $"Temporarily banning client {kickClientID} ({kickClient.IPAddress})."); - server.SendLocalizedMessage(TempBan, Translation.Arguments("admin", client.Name, "client", kickClient.Name)); + server.SendLocalizedMessage(TempBan, Translation.Arguments("admin", client.Name, "player", kickClient.Name)); server.TempBans.Add(kickClient.IPAddress); } diff --git a/OpenRA.Mods.Common/Widgets/ConfirmationDialogs.cs b/OpenRA.Mods.Common/Widgets/ConfirmationDialogs.cs index 8da9abc783..ef29054aa2 100644 --- a/OpenRA.Mods.Common/Widgets/ConfirmationDialogs.cs +++ b/OpenRA.Mods.Common/Widgets/ConfirmationDialogs.cs @@ -10,6 +10,7 @@ #endregion using System; +using System.Collections.Generic; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets @@ -17,8 +18,11 @@ namespace OpenRA.Mods.Common.Widgets public static class ConfirmationDialogs { public static void ButtonPrompt( + ModData modData, string title, string text, + Dictionary titleArguments = null, + Dictionary textArguments = null, Action onConfirm = null, Action onCancel = null, Action onOther = null, @@ -32,10 +36,12 @@ namespace OpenRA.Mods.Common.Widgets var cancelButton = prompt.GetOrNull("CANCEL_BUTTON"); var otherButton = prompt.GetOrNull("OTHER_BUTTON"); - prompt.Get("PROMPT_TITLE").GetText = () => title; + var titleMessage = modData.Translation.GetString(title, titleArguments); + prompt.Get("PROMPT_TITLE").GetText = () => titleMessage; var headerTemplate = prompt.Get("PROMPT_TEXT"); - var headerLines = text.Replace("\\n", "\n").Split('\n'); + var textMessage = modData.Translation.GetString(text, textArguments); + var headerLines = textMessage.Split('\n'); var headerHeight = 0; foreach (var l in headerLines) { @@ -61,7 +67,10 @@ namespace OpenRA.Mods.Common.Widgets }; if (!string.IsNullOrEmpty(confirmText)) - confirmButton.GetText = () => confirmText; + { + var confirmTextMessage = modData.Translation.GetString(confirmText); + confirmButton.GetText = () => confirmTextMessage; + } } if (onCancel != null && cancelButton != null) @@ -75,7 +84,10 @@ namespace OpenRA.Mods.Common.Widgets }; if (!string.IsNullOrEmpty(cancelText)) - cancelButton.GetText = () => cancelText; + { + var cancelTextMessage = modData.Translation.GetString(cancelText); + cancelButton.GetText = () => cancelTextMessage; + } } if (onOther != null && otherButton != null) @@ -88,11 +100,14 @@ namespace OpenRA.Mods.Common.Widgets }; if (!string.IsNullOrEmpty(otherText)) - otherButton.GetText = () => otherText; + { + var otherTextMessage = modData.Translation.GetString(otherText); + otherButton.GetText = () => otherTextMessage; + } } } - public static void TextInputPrompt( + public static void TextInputPrompt(ModData modData, string title, string prompt, string initialText, Action onAccept, Action onCancel = null, string acceptText = null, string cancelText = null, @@ -102,13 +117,12 @@ namespace OpenRA.Mods.Common.Widgets Func doValidate = null; ButtonWidget acceptButton = null, cancelButton = null; - // Title - panel.Get("PROMPT_TITLE").GetText = () => title; + var titleMessage = modData.Translation.GetString(title); + panel.Get("PROMPT_TITLE").GetText = () => titleMessage; - // Prompt - panel.Get("PROMPT_TEXT").GetText = () => prompt; + var promptMessage = modData.Translation.GetString(prompt); + panel.Get("PROMPT_TEXT").GetText = () => promptMessage; - // Text input var input = panel.Get("INPUT_TEXT"); var isValid = false; input.Text = initialText; @@ -133,10 +147,12 @@ namespace OpenRA.Mods.Common.Widgets input.CursorPosition = input.Text.Length; input.OnTextEdited = () => doValidate(); - // Buttons acceptButton = panel.Get("ACCEPT_BUTTON"); if (!string.IsNullOrEmpty(acceptText)) - acceptButton.GetText = () => acceptText; + { + var acceptTextMessage = modData.Translation.GetString(acceptText); + acceptButton.GetText = () => acceptTextMessage; + } acceptButton.OnClick = () => { @@ -149,7 +165,10 @@ namespace OpenRA.Mods.Common.Widgets cancelButton = panel.Get("CANCEL_BUTTON"); if (!string.IsNullOrEmpty(cancelText)) - cancelButton.GetText = () => cancelText; + { + var cancelTextMessage = modData.Translation.GetString(cancelText); + cancelButton.GetText = () => cancelTextMessage; + } cancelButton.OnClick = () => { @@ -157,7 +176,6 @@ namespace OpenRA.Mods.Common.Widgets onCancel?.Invoke(); }; - // Validation doValidate = () => { if (inputValidator == null) diff --git a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs index 78e343e493..02c0488ed7 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs @@ -60,6 +60,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic float spriteScale; float modelScale; + [TranslationReference("length")] + static readonly string LengthInSeconds = "length-in-seconds"; + + [TranslationReference] + static readonly string AllPackages = "all-packages"; + + readonly string allPackages; + [ObjectCreator.UseCtor] public AssetBrowserLogic(Widget widget, Action onExit, ModData modData, WorldRenderer worldRenderer) { @@ -67,6 +75,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.modData = modData; panel = widget; + allPackages = modData.Translation.GetString(AllPackages); + var colorPickerPalettes = world.WorldActor.TraitsImplementing() .SelectMany(p => p.ColorPickerPaletteNames) .ToArray(); @@ -194,13 +204,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic var frameText = panel.GetOrNull("FRAME_COUNT"); if (frameText != null) { + var soundLength = new CachedTransform(p => + modData.Translation.GetString(LengthInSeconds, Translation.Arguments("length", p))); frameText.GetText = () => { if (isVideoLoaded) return $"{player.Video.CurrentFrameIndex + 1} / {player.Video.FrameCount}"; if (currentSoundFormat != null) - return $"{Math.Round(currentSoundFormat.LengthInSeconds, 3)} sec"; + return soundLength.Update((int)currentSoundFormat.LengthInSeconds); return $"{currentFrame} / {currentSprites.Length - 1}"; }; @@ -607,7 +619,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic string GetSourceDisplayName(IReadOnlyPackage source) { if (source == null) - return "All Packages"; + return allPackages; // Packages that are explicitly mounted in the filesystem use their explicit mount name var fs = (OpenRA.FileSystem.FileSystem)modData.DefaultFileSystem; diff --git a/OpenRA.Mods.Common/Widgets/Logic/ConnectionLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ConnectionLogic.cs index 2ebb4b6f54..c4c9148c3c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ConnectionLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ConnectionLogic.cs @@ -21,6 +21,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly Action onAbort; readonly Action onRetry; + [TranslationReference("endpoint")] + static readonly string ConnectingToEndpoint = "connecting-to-endpoint"; + void ConnectionStateChanged(OrderManager om, string password, NetworkConnection connection) { if (connection.ConnectionState == ConnectionState.Connected) @@ -51,7 +54,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } [ObjectCreator.UseCtor] - public ConnectionLogic(Widget widget, ConnectionTarget endpoint, Action onConnect, Action onAbort, Action onRetry) + public ConnectionLogic(Widget widget, ModData modData, ConnectionTarget endpoint, Action onConnect, Action onAbort, Action onRetry) { this.onConnect = onConnect; this.onAbort = onAbort; @@ -62,7 +65,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var panel = widget; panel.Get("ABORT_BUTTON").OnClick = () => { CloseWindow(); onAbort(); }; - widget.Get("CONNECTING_DESC").GetText = () => $"Connecting to {endpoint}..."; + var connectingDesc = modData.Translation.GetString(ConnectingToEndpoint, Translation.Arguments("endpoint", endpoint)); + widget.Get("CONNECTING_DESC").GetText = () => connectingDesc; } public static void Connect(ConnectionTarget endpoint, string password, Action onConnect, Action onAbort) @@ -85,6 +89,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly PasswordFieldWidget passwordField; bool passwordOffsetAdjusted; + [TranslationReference("target")] + static readonly string CouldNotConnectToTarget = "could-not-connect-to-target"; + + [TranslationReference] + static readonly string UnknownError = "unknown-error"; + + [TranslationReference] + static readonly string PasswordRequired = "password-required"; + + [TranslationReference] + static readonly string ConnectionFailed = "connection-failed"; + [ObjectCreator.UseCtor] public ConnectionFailedLogic(Widget widget, ModData modData, OrderManager orderManager, NetworkConnection connection, string password, Action onAbort, Action onRetry) { @@ -104,13 +120,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic onRetry(pass); }; - widget.Get("CONNECTING_DESC").GetText = () => $"Could not connect to {connection.Target}"; + var connectingDescText = modData.Translation.GetString(CouldNotConnectToTarget, Translation.Arguments("target", connection.Target)); + widget.Get("CONNECTING_DESC").GetText = () => connectingDescText; var connectionError = widget.Get("CONNECTION_ERROR"); - connectionError.GetText = () => modData.Translation.GetString(orderManager.ServerError) ?? connection.ErrorMessage ?? "Unknown error"; + var connectionErrorText = modData.Translation.GetString(orderManager.ServerError) ?? connection.ErrorMessage ?? modData.Translation.GetString(UnknownError); + connectionError.GetText = () => connectionErrorText; var panelTitle = widget.Get("TITLE"); - panelTitle.GetText = () => orderManager.AuthenticationFailed ? "Password Required" : "Connection Failed"; + var panelTitleText = orderManager.AuthenticationFailed ? modData.Translation.GetString(PasswordRequired) : modData.Translation.GetString(ConnectionFailed); + panelTitle.GetText = () => panelTitleText; passwordField = panel.GetOrNull("PASSWORD"); if (passwordField != null) @@ -151,6 +170,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class ConnectionSwitchModLogic : ChromeLogic { + [TranslationReference] + static readonly string ModSwitchFailed = "mod-switch-failed"; + [ObjectCreator.UseCtor] public ConnectionSwitchModLogic(Widget widget, OrderManager orderManager, NetworkConnection connection, Action onAbort, Action onRetry) { @@ -167,7 +189,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var launchCommand = $"Launch.URI={new UriBuilder("tcp", connection.EndPoint.Address.ToString(), connection.EndPoint.Port)}"; Game.SwitchToExternalMod(CurrentServerSettings.ServerExternalMod, new[] { launchCommand }, () => { - orderManager.ServerError = "Failed to switch mod."; + orderManager.ServerError = ModSwitchFailed; Ui.CloseWindow(); Ui.OpenWindow("CONNECTIONFAILED_PANEL", new WidgetArgs() { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/CommonSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/CommonSelectorLogic.cs index 31d6c930f0..9801143c01 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/CommonSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/CommonSelectorLogic.cs @@ -71,22 +71,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic return true; }; + var none = ModData.Translation.GetString(None); + var searchResults = ModData.Translation.GetString(SearchResults); + var all = ModData.Translation.GetString(All); + var multiple = ModData.Translation.GetString(Multiple); + var categorySelector = widget.Get("CATEGORIES_DROPDOWN"); categorySelector.GetText = () => { if (SelectedCategories.Count == 0) - return ModData.Translation.GetString(None); + return none; if (!string.IsNullOrEmpty(searchFilter)) - return ModData.Translation.GetString(SearchResults); + return searchResults; if (SelectedCategories.Count == 1) return SelectedCategories.First(); if (SelectedCategories.Count == allCategories.Length) - return ModData.Translation.GetString(All); + return all; - return ModData.Translation.GetString(Multiple); + return multiple; }; categorySelector.OnMouseDown = _ => diff --git a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs index 186df0f1a2..878e00b93f 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Editor/SaveMapLogic.cs @@ -42,6 +42,36 @@ namespace OpenRA.Mods.Common.Widgets.Logic } } + [TranslationReference] + static readonly string SaveMapFailedTitle = "save-map-failed-title"; + + [TranslationReference] + static readonly string SaveMapFailedPrompt = "save-map-failed-prompt"; + + [TranslationReference] + static readonly string SaveMapFailedAccept = "save-map-failed-accept"; + + [TranslationReference] + static readonly string Unpacked = "unpacked"; + + [TranslationReference] + static readonly string OverwriteMapFailedTitle = "overwrite-map-failed-title"; + + [TranslationReference] + static readonly string OverwriteMapFailedPrompt = "overwrite-map-failed-prompt"; + + [TranslationReference] + static readonly string SaveMapFailedConfirm = "overwrite-map-failed-confirm"; + + [TranslationReference] + static readonly string OverwriteMapOutsideEditTitle = "overwrite-map-outside-edit-title"; + + [TranslationReference] + static readonly string OverwriteMapOutsideEditPrompt = "overwrite-map-outside-edit-prompt"; + + [TranslationReference] + static readonly string SaveMapMapOutsideConfirm = "overwrite-map-outside-edit-confirm"; + [ObjectCreator.UseCtor] public SaveMapLogic(Widget widget, ModData modData, Action onSave, Action onExit, Map map, List playerDefinitions, List actorDefinitions) @@ -135,7 +165,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var fileTypes = new Dictionary() { { MapFileType.OraMap, new MapFileTypeInfo { Extension = ".oramap", UiLabel = ".oramap" } }, - { MapFileType.Unpacked, new MapFileTypeInfo { Extension = "", UiLabel = "(unpacked)" } } + { MapFileType.Unpacked, new MapFileTypeInfo { Extension = "", UiLabel = $"({modData.Translation.GetString(Unpacked)})" } } }; var typeDropdown = widget.Get("TYPE_DROPDOWN"); @@ -192,11 +222,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic Log.Write("debug", $"Failed to save map at {combinedPath}"); Log.Write("debug", e); - ConfirmationDialogs.ButtonPrompt( - title: "Failed to save map", - text: "See debug.log for details.", + ConfirmationDialogs.ButtonPrompt(modData, + title: SaveMapFailedTitle, + text: SaveMapFailedPrompt, onConfirm: () => { }, - confirmText: "OK"); + confirmText: SaveMapFailedAccept); } }; @@ -213,10 +243,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic // When creating a new map or when file paths don't match if (modData.MapCache.Any(m => m.Status == MapStatus.Available && m.Package?.Name == combinedPath)) { - ConfirmationDialogs.ButtonPrompt( - title: "Warning", - text: "By saving you will overwrite\n an already existing map.", - confirmText: "Save", + ConfirmationDialogs.ButtonPrompt(modData, + title: OverwriteMapFailedTitle, + text: OverwriteMapFailedPrompt, + confirmText: SaveMapFailedConfirm, onConfirm: () => saveMap(combinedPath), onCancel: () => { }); @@ -229,10 +259,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var recentUid = modData.MapCache.GetUpdatedMap(map.Uid); if (recentUid != null && map.Uid != recentUid && modData.MapCache[recentUid].Status == MapStatus.Available) { - ConfirmationDialogs.ButtonPrompt( - title: "Warning", - text: "The map has been edited from outside the editor.\n By saving you may overwrite progress", - confirmText: "Save", + ConfirmationDialogs.ButtonPrompt(modData, + title: OverwriteMapOutsideEditTitle, + text: OverwriteMapOutsideEditPrompt, + confirmText: SaveMapMapOutsideConfirm, onConfirm: () => saveMap(combinedPath), onCancel: () => { }); diff --git a/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs index 42245071f3..ae9aabfef6 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/GameSaveBrowserLogic.cs @@ -33,6 +33,45 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly string defaultSaveFilename; string selectedSave; + [TranslationReference] + static readonly string RenameSaveTitle = "rename-save-title"; + + [TranslationReference] + static readonly string RenameSavePrompt = "rename-save-prompt"; + + [TranslationReference] + static readonly string RenameSaveAccept = "rename-save-accept"; + + [TranslationReference] + static readonly string DeleteSaveTitle = "delete-save-title"; + + [TranslationReference("save")] + static readonly string DeleteSavePrompt = "delete-save-prompt"; + + [TranslationReference] + static readonly string DeleteSaveAccept = "delete-save-accept"; + + [TranslationReference] + static readonly string DeleteAllSavesTitle = "delete-all-saves-title"; + + [TranslationReference("count")] + static readonly string DeleteAllSavesPrompt = "delete-all-saves-prompt"; + + [TranslationReference] + static readonly string DeleteAllSavesAccept = "delete-all-saves-accept"; + + [TranslationReference("savePath")] + static readonly string SaveDeletionFailed = "save-deletion-failed"; + + [TranslationReference] + static readonly string OverwriteSaveTitle = "overwrite-save-title"; + + [TranslationReference("file")] + static readonly string OverwriteSavePrompt = "overwrite-save-prompt"; + + [TranslationReference] + static readonly string OverwriteSaveAccpet = "overwrite-save-accept"; + [ObjectCreator.UseCtor] public GameSaveBrowserLogic(Widget widget, ModData modData, Action onExit, Action onStart, bool isSavePanel, World world) { @@ -100,13 +139,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic var initialName = Path.GetFileNameWithoutExtension(selectedSave); var invalidChars = Path.GetInvalidFileNameChars(); - ConfirmationDialogs.TextInputPrompt( - "Rename Save", - "Enter a new file name:", + ConfirmationDialogs.TextInputPrompt(modData, + RenameSaveTitle, + RenameSavePrompt, initialName, onAccept: newName => Rename(initialName, newName), onCancel: null, - acceptText: "Rename", + acceptText: RenameSaveAccept, cancelText: null, inputValidator: newName => { @@ -130,9 +169,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic deleteButton.IsDisabled = () => selectedSave == null; deleteButton.OnClick = () => { - ConfirmationDialogs.ButtonPrompt( - title: "Delete selected game save?", - text: $"Delete '{Path.GetFileNameWithoutExtension(selectedSave)}'?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteSaveTitle, + text: DeleteSavePrompt, + textArguments: Translation.Arguments("save", Path.GetFileNameWithoutExtension(selectedSave)), onConfirm: () => { Delete(selectedSave); @@ -145,7 +185,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic else SelectFirstVisible(); }, - confirmText: "Delete", + confirmText: DeleteSaveAccept, onCancel: () => { }); }; @@ -153,9 +193,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic deleteAllButton.IsDisabled = () => games.Count == 0; deleteAllButton.OnClick = () => { - ConfirmationDialogs.ButtonPrompt( - title: "Delete all game saves?", - text: $"Delete {games.Count} game saves?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteAllSavesTitle, + text: DeleteAllSavesPrompt, + textArguments: Translation.Arguments("count", games.Count), onConfirm: () => { foreach (var s in games.ToList()) @@ -164,7 +205,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic Ui.CloseWindow(); onExit(); }, - confirmText: "Delete All", + confirmText: DeleteAllSavesAccept, onCancel: () => { }); }; @@ -251,7 +292,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } catch (Exception ex) { - TextNotificationsManager.Debug("Failed to delete save file '{0}'. See the logs for details.", savePath); + TextNotificationsManager.Debug(modData.Translation.GetString(SaveDeletionFailed, Translation.Arguments("savePath", savePath))); Log.Write("debug", ex.ToString()); return; } @@ -319,11 +360,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (selectedSave != null || File.Exists(testPath)) { - ConfirmationDialogs.ButtonPrompt( - title: "Overwrite save game?", - text: $"Overwrite {saveTextField.Text}?", + ConfirmationDialogs.ButtonPrompt(modData, + title: OverwriteSaveTitle, + text: OverwriteSavePrompt, + textArguments: Translation.Arguments("file", saveTextField.Text), onConfirm: inner, - confirmText: "Overwrite", + confirmText: OverwriteSaveAccpet, onCancel: () => { }); } else diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoStatsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoStatsLogic.cs index e5d0e3c816..e61003b164 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoStatsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/GameInfoStatsLogic.cs @@ -28,6 +28,36 @@ namespace OpenRA.Mods.Common.Widgets.Logic [TranslationReference] static readonly string Mute = "mute"; + [TranslationReference] + static readonly string Accomplished = "accomplished"; + + [TranslationReference] + static readonly string Failed = "failed"; + + [TranslationReference] + static readonly string InProgress = "in-progress"; + + [TranslationReference("team")] + static readonly string TeamNumber = "team-number"; + + [TranslationReference] + static readonly string NoTeam = "no-team"; + + [TranslationReference] + static readonly string Spectators = "spectators"; + + [TranslationReference] + static readonly string Gone = "gone"; + + [TranslationReference("player")] + static readonly string KickTitle = "kick-title"; + + [TranslationReference] + static readonly string KickPrompt = "kick-prompt"; + + [TranslationReference] + static readonly string KickAccept = "kick-accept"; + [ObjectCreator.UseCtor] public GameInfoStatsLogic(Widget widget, ModData modData, World world, OrderManager orderManager, WorldRenderer worldRenderer, Action hideMenu) { @@ -49,8 +79,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic checkbox.GetText = () => mo.Objectives.First().Description; } - statusLabel.GetText = () => player.WinState == WinState.Won ? "Accomplished" : - player.WinState == WinState.Lost ? "Failed" : "In progress"; + statusLabel.GetText = () => player.WinState == WinState.Won ? Accomplished : + player.WinState == WinState.Lost ? Failed : InProgress; statusLabel.GetColor = () => player.WinState == WinState.Won ? Color.LimeGreen : player.WinState == WinState.Lost ? Color.Red : Color.White; } @@ -86,7 +116,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (teams.Count() > 1) { var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); - teamHeader.Get("TEAM").GetText = () => t.Key == 0 ? "No Team" : $"Team {t.Key}"; + var team = t.Key > 0 + ? modData.Translation.GetString(TeamNumber, Translation.Arguments("team", t.Key)) + : modData.Translation.GetString(NoTeam); + teamHeader.Get("TEAM").GetText = () => team; var teamRating = teamHeader.Get("TEAM_SCORE"); var scoreCache = new CachedTransform(s => s.ToString()); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience); @@ -137,7 +170,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (spectators.Count > 0) { var spectatorHeader = ScrollItemWidget.Setup(teamTemplate, () => true, () => { }); - spectatorHeader.Get("TEAM").GetText = () => "Spectators"; + var spectatorTeam = modData.Translation.GetString(Spectators); + spectatorHeader.Get("TEAM").GetText = () => spectatorTeam; playerPanel.AddChild(spectatorHeader); @@ -155,7 +189,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic nameLabel.GetText = () => { - var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; + var suffix = client.State == Session.ClientState.Disconnected ? $" ({modData.Translation.GetString(Gone)})" : ""; return name.Update((client.Name, suffix)); }; @@ -164,16 +198,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic kickButton.OnClick = () => { hideMenu(true); - ConfirmationDialogs.ButtonPrompt( - title: $"Kick {client.Name}?", - text: "They will not be able to rejoin this game.", + ConfirmationDialogs.ButtonPrompt(modData, + title: KickTitle, + titleArguments: Translation.Arguments("player", client.Name), + text: KickPrompt, onConfirm: () => { orderManager.IssueOrder(Order.Command($"kick {client.Index} {false}")); hideMenu(false); }, onCancel: () => hideMenu(false), - confirmText: "Kick"); + confirmText: KickAccept); }; var muteCheckbox = item.Get("MUTE"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs index 0014ba1c63..54eafa8b7d 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameChatLogic.cs @@ -32,7 +32,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ContainerWidget chatChrome; readonly ScrollPanelWidget chatScrollPanel; readonly TextFieldWidget chatText; - readonly CachedTransform chatDisabledLabel; + readonly CachedTransform chatAvailableIn; + readonly string chatDisabled; readonly Dictionary templates = new Dictionary(); readonly TabCompletionLogic tabCompletion = new TabCompletionLogic(); @@ -52,6 +53,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic [TranslationReference("seconds")] static readonly string ChatAvailability = "chat-availability"; + [TranslationReference] + static readonly string ChatDisabled = "chat-disabled"; + [ObjectCreator.UseCtor] public IngameChatLogic(Widget widget, OrderManager orderManager, World world, ModData modData, bool isMenuChat, Dictionary logicArgs) { @@ -69,6 +73,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var teamMessage = modData.Translation.GetString(Team); var allMessage = modData.Translation.GetString(All); + chatDisabled = modData.Translation.GetString(ChatDisabled); + // Only execute this once, the first time this widget is loaded if (TextNotificationsManager.MutedPlayers.Count == 0) foreach (var c in orderManager.LobbyInfo.Clients) @@ -188,7 +194,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return true; }; - chatDisabledLabel = new CachedTransform(x => modData.Translation.GetString(ChatAvailability, Translation.Arguments("seconds", x))); + chatAvailableIn = new CachedTransform(x => modData.Translation.GetString(ChatAvailability, Translation.Arguments("seconds", x))); if (!isMenuChat) { @@ -320,7 +326,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (TextNotificationsManager.ChatDisabledUntil != uint.MaxValue) remaining = (int)(TextNotificationsManager.ChatDisabledUntil - Game.RunTime + 999) / 1000; - chatText.Text = chatDisabledLabel.Update(remaining); + chatText.Text = remaining == 0 ? chatDisabled : chatAvailableIn.Update(remaining); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs index 838c7d6967..f0825987df 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/IngameMenuLogic.cs @@ -37,6 +37,102 @@ namespace OpenRA.Mods.Common.Widgets.Logic bool leaving; bool hideMenu; + [TranslationReference] + static readonly string Leave = "leave"; + + [TranslationReference] + static readonly string AbortMission = "abort-mission"; + + [TranslationReference] + static readonly string LeaveMissionTitle = "leave-mission-title"; + + [TranslationReference] + static readonly string LeaveMissionPrompt = "leave-mission-prompt"; + + [TranslationReference] + static readonly string LeaveMissionAccept = "leave-mission-accept"; + + [TranslationReference] + static readonly string LeaveMissionCancel = "leave-mission-cancel"; + + [TranslationReference] + static readonly string RestartButton = "restart-button"; + + [TranslationReference] + static readonly string RestartMissionTitle = "restart-mission-title"; + + [TranslationReference] + static readonly string RestartMissionPrompt = "restart-mission-prompt"; + + [TranslationReference] + static readonly string RestartMissionAccept = "restart-mission-accept"; + + [TranslationReference] + static readonly string RestartMissionCancel = "restart-mission-cancel"; + + [TranslationReference] + static readonly string SurrenderButton = "surrender-button"; + + [TranslationReference] + static readonly string SurrenderTitle = "surrender-title"; + + [TranslationReference] + static readonly string SurrenderPrompt = "surrender-prompt"; + + [TranslationReference] + static readonly string SurrenderAccept = "surrender-accept"; + + [TranslationReference] + static readonly string SurrenderCancel = "surrender-cancel"; + + [TranslationReference] + static readonly string LoadGameButton = "load-game-button"; + + [TranslationReference] + static readonly string SaveGameButton = "save-game-button"; + + [TranslationReference] + static readonly string MusicButton = "music-button"; + + [TranslationReference] + static readonly string SettingsButton = "settings-button"; + + [TranslationReference] + static readonly string ReturnToMap = "return-to-map"; + + [TranslationReference] + static readonly string Resume = "resume"; + + [TranslationReference] + static readonly string SaveMapButton = "save-map-button"; + + [TranslationReference] + static readonly string ErrorMaxPlayerTitle = "error-max-player-title"; + + [TranslationReference("players", "max")] + static readonly string ErrorMaxPlayerPrompt = "error-max-player-prompt"; + + [TranslationReference] + static readonly string ErrorMaxPlayerAccept = "error-max-player-accept"; + + [TranslationReference] + static readonly string ExitMapButton = "exit-map-button"; + + [TranslationReference] + static readonly string ExitMapEditorTitle = "exit-map-editor-title"; + + [TranslationReference] + static readonly string ExitMapEditorPromptUnsaved = "exit-map-editor-prompt-unsaved"; + + [TranslationReference] + static readonly string ExitMapEditorPromptDeleted = "exit-map-editor-prompt-deleted"; + + [TranslationReference] + static readonly string ExitMapEditorAnywayConfirm = "exit-map-editor-confirm-anyway"; + + [TranslationReference] + static readonly string ExitMapEditorConfirm = "exit-map-editor-confirm"; + [ObjectCreator.UseCtor] public IngameMenuLogic(Widget widget, ModData modData, World world, Action onExit, WorldRenderer worldRenderer, IngameInfoPanel initialPanel, Dictionary logicArgs) @@ -175,7 +271,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic button.Id = id; button.IsDisabled = () => leaving; - button.GetText = () => text; + var translation = modData.Translation.GetString(text); + button.GetText = () => translation; buttonContainer.AddChild(button); buttons.Add(button); @@ -187,19 +284,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (world.Type != WorldType.Regular) return; - var button = AddButton("ABORT_MISSION", world.IsGameOver ? "Leave" : "Abort Mission"); + var button = AddButton("ABORT_MISSION", world.IsGameOver + ? modData.Translation.GetString(Leave) + : modData.Translation.GetString(AbortMission)); button.OnClick = () => { hideMenu = true; - ConfirmationDialogs.ButtonPrompt( - title: "Leave Mission", - text: "Leave this game and return to the menu?", + ConfirmationDialogs.ButtonPrompt(modData, + title: LeaveMissionTitle, + text: LeaveMissionPrompt, onConfirm: OnQuit, onCancel: ShowMenu, - confirmText: "Leave", - cancelText: "Stay"); + confirmText: LeaveMissionAccept, + cancelText: LeaveMissionCancel); }; } @@ -224,18 +323,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic Game.RunAfterDelay(exitDelay, Game.RestartGame); }; - var button = AddButton("RESTART", "Restart"); + var button = AddButton("RESTART", RestartButton); button.IsDisabled = () => hasError || leaving; button.OnClick = () => { hideMenu = true; - ConfirmationDialogs.ButtonPrompt( - title: "Restart", - text: "Are you sure you want to restart?", + ConfirmationDialogs.ButtonPrompt(modData, + title: RestartMissionTitle, + text: RestartMissionPrompt, onConfirm: onRestart, onCancel: ShowMenu, - confirmText: "Restart", - cancelText: "Stay"); + confirmText: RestartMissionAccept, + cancelText: RestartMissionCancel); }; } @@ -250,18 +349,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic CloseMenu(); }; - var button = AddButton("SURRENDER", "Surrender"); + var button = AddButton("SURRENDER", SurrenderButton); button.IsDisabled = () => world.LocalPlayer.WinState != WinState.Undefined || hasError || leaving; button.OnClick = () => { hideMenu = true; - ConfirmationDialogs.ButtonPrompt( - title: "Surrender", - text: "Are you sure you want to surrender?", + ConfirmationDialogs.ButtonPrompt(modData, + title: SurrenderTitle, + text: SurrenderPrompt, onConfirm: onSurrender, onCancel: ShowMenu, - confirmText: "Surrender", - cancelText: "Stay"); + confirmText: SurrenderAccept, + cancelText: SurrenderCancel); }; } @@ -270,7 +369,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (world.Type != WorldType.Regular || !world.LobbyInfo.GlobalSettings.GameSavesEnabled || world.IsReplay) return; - var button = AddButton("LOAD_GAME", "Load Game"); + var button = AddButton("LOAD_GAME", LoadGameButton); button.IsDisabled = () => leaving || !GameSaveBrowserLogic.IsLoadPanelEnabled(modData.Manifest); button.OnClick = () => { @@ -290,7 +389,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (world.Type != WorldType.Regular || !world.LobbyInfo.GlobalSettings.GameSavesEnabled || world.IsReplay) return; - var button = AddButton("SAVE_GAME", "Save Game"); + var button = AddButton("SAVE_GAME", SaveGameButton); button.IsDisabled = () => hasError || leaving || !world.Players.Any(p => p.Playable && p.WinState == WinState.Undefined); button.OnClick = () => { @@ -307,7 +406,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void CreateMusicButton() { - var button = AddButton("MUSIC", "Music"); + var button = AddButton("MUSIC", MusicButton); button.OnClick = () => { hideMenu = true; @@ -321,7 +420,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void CreateSettingsButton() { - var button = AddButton("SETTINGS", "Settings"); + var button = AddButton("SETTINGS", SettingsButton); button.OnClick = () => { hideMenu = true; @@ -336,7 +435,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void CreateResumeButton() { - var button = AddButton("RESUME", world.IsGameOver ? "Return to map" : "Resume"); + var button = AddButton("RESUME", world.IsGameOver ? ReturnToMap : Resume); button.Key = modData.Hotkeys["escape"]; button.OnClick = CloseMenu; } @@ -346,7 +445,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (world.Type != WorldType.Editor) return; - var button = AddButton("SAVE_MAP", "Save Map"); + var button = AddButton("SAVE_MAP", SaveMapButton); button.OnClick = () => { hideMenu = true; @@ -358,11 +457,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic var playerCount = new MapPlayers(playerDefinitions).Players.Count; if (playerCount > MapPlayers.MaximumPlayerCount) { - ConfirmationDialogs.ButtonPrompt( - title: "Error: Max player count exceeded", - text: $"There are too many players defined ({playerCount}/{MapPlayers.MaximumPlayerCount}).", + ConfirmationDialogs.ButtonPrompt(modData, + title: ErrorMaxPlayerTitle, + text: ErrorMaxPlayerPrompt, + textArguments: Translation.Arguments("players", playerCount, "max", MapPlayers.MaximumPlayerCount), onConfirm: ShowMenu, - confirmText: "Back"); + confirmText: ErrorMaxPlayerAccept); return; } @@ -384,7 +484,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return; var actionManager = world.WorldActor.Trait(); - var button = AddButton("EXIT_EDITOR", "Exit Map Editor"); + var button = AddButton("EXIT_EDITOR", ExitMapButton); // Show dialog only if updated since last save button.OnClick = () => @@ -394,10 +494,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (actionManager.HasUnsavedItems() || deletedOrUnavailable) { hideMenu = true; - ConfirmationDialogs.ButtonPrompt( - title: "Warning", - text: deletedOrUnavailable ? "The map may have been deleted outside the editor" : "Exit and lose all unsaved changes?", - confirmText: deletedOrUnavailable ? "Exit anyway" : "Exit", + ConfirmationDialogs.ButtonPrompt(modData, + title: ExitMapEditorTitle, + text: deletedOrUnavailable ? ExitMapEditorPromptDeleted : ExitMapEditorPromptUnsaved, + confirmText: deletedOrUnavailable ? ExitMapEditorAnywayConfirm : ExitMapEditorConfirm, onConfirm: OnQuit, onCancel: ShowMenu); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverShroudSelectorLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverShroudSelectorLogic.cs index 0b6d020a64..30bda07dae 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverShroudSelectorLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverShroudSelectorLogic.cs @@ -48,7 +48,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic static readonly string Players = "players"; [TranslationReference("team")] - static readonly string Team = "team-no-team"; + static readonly string TeamNumber = "team-number"; + + [TranslationReference] + static readonly string NoTeam = "no-team"; class CameraOption { @@ -116,7 +119,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic foreach (var t in teams) { totalPlayers += t.Count(); - var label = noTeams ? modData.Translation.GetString(Players) : modData.Translation.GetString(Team, Translation.Arguments("team", t.Key)); + var label = noTeams ? modData.Translation.GetString(Players) : t.Key > 0 + ? modData.Translation.GetString(TeamNumber, Translation.Arguments("team", t.Key)) + : modData.Translation.GetString(NoTeam); + groups.Add(label, t); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs index 540994cd74..ac1110a32a 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Ingame/ObserverStatsLogic.cs @@ -82,7 +82,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic static readonly string ArmyGraph = "army-graph"; [TranslationReference("team")] - static readonly string Team = "team-no-team"; + static readonly string TeamNumber = "team-number"; + + [TranslationReference] + static readonly string NoTeam = "no-team"; [ObjectCreator.UseCtor] public ObserverStatsLogic(World world, ModData modData, WorldRenderer worldRenderer, Widget widget, Dictionary logicArgs) @@ -91,7 +94,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.worldRenderer = worldRenderer; MiniYaml yaml; - string[] keyNames = Enum.GetNames(typeof(ObserverStatsPanel)); + var keyNames = Enum.GetNames(typeof(ObserverStatsPanel)); var statsHotkeys = new HotkeyReference[keyNames.Length]; for (var i = 0; i < keyNames.Length; i++) statsHotkeys[i] = logicArgs.TryGetValue("Statistics" + keyNames[i] + "Key", out yaml) ? modData.Hotkeys[yaml.Value] : new HotkeyReference(); @@ -144,7 +147,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic title = modData.Translation.GetString(title); return new StatsDropDownOption { - Title = title, + Title = modData.Translation.GetString(title), IsSelected = () => activePanel == panel, OnClick = () => { @@ -272,9 +275,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic tt.IgnoreMouseOver = true; var teamLabel = tt.Get("TEAM"); - var teamText = modData.Translation.GetString(Team, Translation.Arguments("team-no-team", team.Key)); + var teamText = team.Key > 0 ? modData.Translation.GetString(TeamNumber, Translation.Arguments("team", team.Key)) + : modData.Translation.GetString(NoTeam); teamLabel.GetText = () => teamText; - tt.Bounds.Width = teamLabel.Bounds.Width = Game.Renderer.Fonts[tt.Font].Measure(tt.Get("TEAM").GetText()).X; + tt.Bounds.Width = teamLabel.Bounds.Width = Game.Renderer.Fonts[tt.Font].Measure(teamText).X; var colorBlockWidget = tt.Get("TEAM_COLOR"); var scrollBarOffset = playerStatsPanel.ScrollBar != ScrollBar.Hidden diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs index fa858e6974..4548360c76 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/DownloadPackageLogic.cs @@ -24,6 +24,41 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class DownloadPackageLogic : ChromeLogic { static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; + + [TranslationReference("title")] + static readonly string Downloading = "downloading"; + + [TranslationReference] + static readonly string FetchingMirrorList = "fetching-mirror-list"; + + [TranslationReference] + static readonly string UnknownHost = "unknown-host"; + + [TranslationReference("host", "received", "suffix")] + static readonly string DownloadingFrom = "downloading-from"; + + [TranslationReference("host", "received", "total", "suffix", "progress")] + static readonly string DownloadingFromProgress = "downloading-from-progress"; + + [TranslationReference] + static readonly string VerifyingArchive = "verifying-archive"; + + [TranslationReference] + static readonly string ArchiveValidationFailed = "archive-validation-failed"; + + [TranslationReference] + static readonly string Extracting = "extracting"; + + [TranslationReference("entry")] + static readonly string ExtractingEntry = "extracting-entry"; + + [TranslationReference] + static readonly string ArchiveExtractionFailed = "archive-extraction-failed"; + + [TranslationReference] + static readonly string MirrorSelectionFailed = "mirror-selection-failed"; + + readonly ModData modData; readonly ModContent.ModDownload download; readonly Action onSuccess; @@ -34,8 +69,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic string downloadHost; [ObjectCreator.UseCtor] - public DownloadPackageLogic(Widget widget, ModContent.ModDownload download, Action onSuccess) + public DownloadPackageLogic(Widget widget, ModData modData, ModContent.ModDownload download, Action onSuccess) { + this.modData = modData; this.download = download; this.onSuccess = onSuccess; @@ -49,7 +85,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var status = new CachedTransform(s => WidgetUtils.TruncateText(s, statusLabel.Bounds.Width, statusFont)); statusLabel.GetText = () => status.Update(getStatusText()); - var text = $"Downloading {download.Title}"; + var text = modData.Translation.GetString(Downloading, Translation.Arguments("title", download.Title)); panel.Get("TITLE").Text = text; ShowDownloadDialog(); @@ -57,7 +93,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void ShowDownloadDialog() { - getStatusText = () => "Fetching list of mirrors..."; + getStatusText = () => modData.Translation.GetString(FetchingMirrorList); progressBar.Indeterminate = true; var retryButton = panel.Get("RETRY_BUTTON"); @@ -71,6 +107,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var dataTotal = 0.0f; var mag = 0; var dataSuffix = ""; + var host = downloadHost ?? UnknownHost; if (total < 0) { @@ -78,7 +115,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic dataReceived = read / (float)(1L << (mag * 10)); dataSuffix = SizeSuffixes[mag]; - getStatusText = () => $"Downloading from {downloadHost ?? "unknown host"} {dataReceived:0.00} {dataSuffix}"; + getStatusText = () => modData.Translation.GetString(DownloadingFrom, + Translation.Arguments("host", host, "received", $"{dataReceived:0.00}", "suffix", dataSuffix)); progressBar.Indeterminate = true; } else @@ -88,7 +126,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic dataReceived = read / (float)(1L << (mag * 10)); dataSuffix = SizeSuffixes[mag]; - getStatusText = () => $"Downloading from {downloadHost ?? "unknown host"} {dataReceived:0.00}/{dataTotal:0.00} {dataSuffix} ({progressPercentage}%)"; + getStatusText = () => modData.Translation.GetString(DownloadingFromProgress, + Translation.Arguments("host", host, "received", $"{dataReceived:0.00}", "total", $"{dataTotal:0.00}", + "suffix", dataSuffix, "progress", progressPercentage)); progressBar.Indeterminate = false; } @@ -142,7 +182,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic // Validate integrity if (!string.IsNullOrEmpty(download.SHA1)) { - getStatusText = () => "Verifying archive..."; + getStatusText = () => modData.Translation.GetString(VerifyingArchive); progressBar.Indeterminate = true; var archiveValid = false; @@ -164,13 +204,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (!archiveValid) { - onError("Archive validation failed"); + onError(modData.Translation.GetString(ArchiveValidationFailed)); return; } } // Automatically extract - getStatusText = () => "Extracting..."; + getStatusText = () => modData.Translation.GetString(Extracting); progressBar.Indeterminate = true; var extracted = new List(); @@ -185,7 +225,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (entry == null || !entry.IsFile) continue; - onExtractProgress("Extracting " + entry.Name); + onExtractProgress(modData.Translation.GetString(ExtractingEntry, Translation.Arguments("entry", entry.Name))); Log.Write("install", "Extracting " + entry.Name); var targetPath = Platform.ResolvePath(kv.Key); Directory.CreateDirectory(Path.GetDirectoryName(targetPath)); @@ -215,7 +255,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic File.Delete(f); } - onError("Archive extraction failed"); + onError(modData.Translation.GetString(ArchiveExtractionFailed)); } } catch (Exception e) @@ -248,7 +288,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { Log.Write("install", "Mirror selection failed with error:"); Log.Write("install", e.ToString()); - onError("Online mirror is not available. Please install from an original disc."); + onError(modData.Translation.GetString(MirrorSelectionFailed)); } }); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromDiscLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromDiscLogic.cs index 59581b5620..72e92d6cf7 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromDiscLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/InstallFromDiscLogic.cs @@ -27,6 +27,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic enum Mode { Progress, Message, List } + readonly ModData modData; readonly ModContent content; readonly Dictionary sources; @@ -53,9 +54,67 @@ namespace OpenRA.Mods.Common.Widgets.Logic Mode visible = Mode.Progress; + [TranslationReference] + static readonly string DetectingDrives = "detecting-drives"; + + [TranslationReference] + static readonly string CheckingDiscs = "checking-discs"; + + [TranslationReference("title")] + static readonly string SearchingDiscFor = "searching-disc-for"; + + [TranslationReference] + static readonly string ContentPackageInstallation = "content-package-installation"; + + [TranslationReference] + static readonly string GameDiscs = "game-discs"; + + [TranslationReference] + static readonly string DigitalInstalls = "digital-installs"; + + [TranslationReference] + static readonly string GameContentNotFound = "game-content-not-found"; + + [TranslationReference] + static readonly string AlternativeContentSources = "alternative-content-sources"; + + [TranslationReference] + static readonly string InstallingContent = "installing-content"; + + [TranslationReference("filename")] + static readonly string CopyingFilename = "copying-filename"; + + [TranslationReference("filename", "progress")] + static readonly string CopyingFilenameProgress = "copying-filename-progress"; + + [TranslationReference] + static readonly string InstallationFailed = "installation-failed"; + + [TranslationReference] + static readonly string CheckInstallLog = "check-install-log"; + + [TranslationReference("filename")] + static readonly string Extracing = "extracting-filename"; + + [TranslationReference("filename", "progress")] + static readonly string ExtracingProgress = "extracting-filename-progress"; + + [TranslationReference] + static readonly string Continue = "continue"; + + [TranslationReference] + static readonly string Cancel = "cancel"; + + [TranslationReference] + static readonly string Retry = "retry"; + + [TranslationReference] + static readonly string Back = "back"; + [ObjectCreator.UseCtor] - public InstallFromDiscLogic(Widget widget, ModContent content, Dictionary sources) + public InstallFromDiscLogic(Widget widget, ModData modData, ModContent content, Dictionary sources) { + this.modData = modData; this.content = content; this.sources = sources; @@ -108,8 +167,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic void DetectContentDisks() { - var message = "Detecting drives"; - ShowProgressbar("Checking Discs", () => message); + var message = modData.Translation.GetString(DetectingDrives); + ShowProgressbar(modData.Translation.GetString(CheckingDiscs), () => message); ShowBackRetry(DetectContentDisks); new Task(() => @@ -132,7 +191,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic foreach (var kv in sources) { - message = "Searching for " + kv.Value.Title; + message = modData.Translation.GetString(SearchingDiscFor, Translation.Arguments("title", kv.Value.Title)); var path = FindSourcePath(kv.Value, volumes); if (path != null) @@ -148,7 +207,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { Game.RunAfterTick(() => { - ShowList(kv.Value.Title, "The following content packages will be installed:", packages); + ShowList(kv.Value.Title, modData.Translation.GetString(ContentPackageInstallation), packages); ShowContinueCancel(() => InstallFromDisc(path, kv.Value)); }); @@ -169,7 +228,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var options = new Dictionary>() { - { "Game Discs", discs }, + { modData.Translation.GetString(GameDiscs), discs }, }; if (Platform.CurrentPlatform == PlatformType.Windows) @@ -179,12 +238,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic .Select(s => s.Title) .Distinct(); - options.Add("Digital Installs", installations); + options.Add(modData.Translation.GetString(DigitalInstalls), installations); } Game.RunAfterTick(() => { - ShowList("Game Content Not Found", "Please insert or install one of the following content sources:", options); + ShowList(modData.Translation.GetString(GameContentNotFound), modData.Translation.GetString(AlternativeContentSources), options); ShowBackRetry(DetectContentDisks); }); }).Start(); @@ -193,7 +252,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void InstallFromDisc(string path, ModContent.ModSource modSource) { var message = ""; - ShowProgressbar("Installing Content", () => message); + ShowProgressbar(modData.Translation.GetString(InstallingContent), () => message); ShowDisabledCancel(); new Task(() => @@ -231,9 +290,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action onProgress = null; if (length < ShowPercentageThreshold) - message = "Copying " + displayFilename; + message = modData.Translation.GetString(CopyingFilename, Translation.Arguments("filename", displayFilename)); else - onProgress = b => message = $"Copying {displayFilename} ({100 * b / length}%)"; + onProgress = b => message = modData.Translation.GetString(CopyingFilenameProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)); CopyStream(source, target, length, onProgress); } @@ -244,25 +303,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic case "extract-raw": { - ExtractFromPackage(ExtractionType.Raw, path, i.Value, extracted, m => message = m); + ExtractFromPackage(modData, ExtractionType.Raw, path, i.Value, extracted, m => message = m); break; } case "extract-blast": { - ExtractFromPackage(ExtractionType.Blast, path, i.Value, extracted, m => message = m); + ExtractFromPackage(modData, ExtractionType.Blast, path, i.Value, extracted, m => message = m); break; } case "extract-mscab": { - ExtractFromMSCab(path, i.Value, extracted, m => message = m); + ExtractFromMSCab(modData, path, i.Value, extracted, m => message = m); break; } case "extract-iscab": { - ExtractFromISCab(path, i.Value, extracted, m => message = m); + ExtractFromISCab(modData, path, i.Value, extracted, m => message = m); break; } @@ -296,7 +355,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic Game.RunAfterTick(() => { - ShowMessage("Installation Failed", "Refer to install.log in the logs directory for details."); + ShowMessage(modData.Translation.GetString(InstallationFailed), modData.Translation.GetString(CheckInstallLog)); ShowBackRetry(() => InstallFromDisc(path, modSource)); }); } @@ -320,7 +379,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic enum ExtractionType { Raw, Blast } - static void ExtractFromPackage(ExtractionType type, string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) + static void ExtractFromPackage(ModData modData, ExtractionType type, string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) { // Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value); @@ -360,9 +419,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action onProgress = null; if (length < ShowPercentageThreshold) - updateMessage("Extracting " + displayFilename); + updateMessage(modData.Translation.GetString(Extracing, Translation.Arguments("filename", displayFilename))); else - onProgress = b => updateMessage($"Extracting {displayFilename} ({100 * b / length}%)"); + onProgress = b => updateMessage(modData.Translation.GetString(ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length))); using (var target = File.OpenWrite(targetPath)) { @@ -376,7 +435,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } } - static void ExtractFromMSCab(string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) + static void ExtractFromMSCab(ModData modData, string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) { // Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value); @@ -400,14 +459,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic { Log.Write("install", $"Extracting {sourcePath} -> {targetPath}"); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); - Action onProgress = percent => updateMessage($"Extracting {displayFilename} ({percent}%)"); + Action onProgress = percent => updateMessage(modData.Translation.GetString(ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent))); reader.ExtractFile(node.Value.Value, target, onProgress); } } } } - static void ExtractFromISCab(string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) + static void ExtractFromISCab(ModData modData, string path, MiniYaml actionYaml, List extractedFiles, Action updateMessage) { // Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected disc path var sourcePath = actionYaml.Value.StartsWith("^") ? Platform.ResolvePath(actionYaml.Value) : Path.Combine(path, actionYaml.Value); @@ -449,7 +508,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { Log.Write("install", $"Extracting {sourcePath} -> {targetPath}"); var displayFilename = Path.GetFileName(Path.GetFileName(targetPath)); - Action onProgress = percent => updateMessage($"Extracting {displayFilename} ({percent}%)"); + Action onProgress = percent => updateMessage(modData.Translation.GetString(ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent))); reader.ExtractFile(node.Value.Value, target, onProgress); } } @@ -627,11 +686,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic void ShowContinueCancel(Action continueAction) { primaryButton.OnClick = continueAction; - primaryButton.Text = "Continue"; + primaryButton.Text = modData.Translation.GetString(Continue); primaryButton.Visible = true; secondaryButton.OnClick = Ui.CloseWindow; - secondaryButton.Text = "Cancel"; + secondaryButton.Text = modData.Translation.GetString(Cancel); secondaryButton.Visible = true; secondaryButton.Disabled = false; Game.RunAfterTick(Ui.ResetTooltips); @@ -640,11 +699,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic void ShowBackRetry(Action retryAction) { primaryButton.OnClick = retryAction; - primaryButton.Text = "Retry"; + primaryButton.Text = modData.Translation.GetString(Retry); primaryButton.Visible = true; secondaryButton.OnClick = Ui.CloseWindow; - secondaryButton.Text = "Back"; + secondaryButton.Text = modData.Translation.GetString(Back); secondaryButton.Visible = true; secondaryButton.Disabled = false; Game.RunAfterTick(Ui.ResetTooltips); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs index 57a1d0d3f2..84032db0c7 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentLogic.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class ModContentLogic : ChromeLogic { + readonly ModData modData; readonly ModContent content; readonly ScrollPanelWidget scrollPanel; readonly Widget template; @@ -29,9 +30,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic bool discAvailable; + [TranslationReference] + static readonly string ManualInstall = "manual-install"; + [ObjectCreator.UseCtor] - public ModContentLogic(Widget widget, Manifest mod, ModContent content, Action onCancel) + public ModContentLogic(ModData modData, Widget widget, Manifest mod, ModContent content, Action onCancel) { + this.modData = modData; this.content = content; var panel = widget.Get("CONTENT_PANEL"); @@ -137,7 +142,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var requiresDiscWidget = container.Get("REQUIRES_DISC"); requiresDiscWidget.IsVisible = () => !installed && !downloadEnabled; if (!isSourceAvailable) - requiresDiscWidget.GetText = () => "Manual Install"; + { + var manualInstall = modData.Translation.GetString(ManualInstall); + requiresDiscWidget.GetText = () => manualInstall; + } scrollPanel.AddChild(container); } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs index e1cc5e5e99..a126b91917 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Installation/ModContentPromptLogic.cs @@ -23,12 +23,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ModContent content; bool requiredContentInstalled; + [TranslationReference] + static readonly string Continue = "continue"; + + [TranslationReference] + static readonly string Quit = "quit"; + [ObjectCreator.UseCtor] - public ModContentPromptLogic(Widget widget, Manifest mod, ModContent content, Action continueLoading) + public ModContentPromptLogic(ModData modData, Widget widget, Manifest mod, ModContent content, Action continueLoading) { this.content = content; CheckRequiredContentInstalled(); + var continueMessage = modData.Translation.GetString(Continue); + var quitMessage = modData.Translation.GetString(Quit); + var panel = widget.Get("CONTENT_PROMPT_PANEL"); var headerTemplate = panel.Get("HEADER_TEMPLATE"); var headerLines = !string.IsNullOrEmpty(content.InstallPromptMessage) ? content.InstallPromptMessage.Replace("\\n", "\n").Split('\n') : Array.Empty(); @@ -83,7 +92,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; var quitButton = panel.Get("QUIT_BUTTON"); - quitButton.GetText = () => requiredContentInstalled ? "Continue" : "Quit"; + quitButton.GetText = () => requiredContentInstalled ? continueMessage : quitMessage; quitButton.Bounds.Y += headerHeight; quitButton.OnClick = () => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs index 9d426796c5..be99bc790a 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/IntroductionPromptLogic.cs @@ -26,6 +26,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic return Game.Settings.Game.IntroductionPromptVersion < IntroductionVersion; } + [TranslationReference] + static readonly string Classic = "classic"; + readonly string classic; + + [TranslationReference] + static readonly string Modern = "modern"; + readonly string modern; + [ObjectCreator.UseCtor] public IntroductionPromptLogic(Widget widget, ModData modData, WorldRenderer worldRenderer, Action onComplete) { @@ -33,6 +41,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic var ds = Game.Settings.Graphics; var gs = Game.Settings.Game; + classic = modData.Translation.GetString(Classic); + modern = modData.Translation.GetString(Modern); + var escPressed = false; var nameTextfield = widget.Get("PLAYERNAME"); nameTextfield.IsDisabled = () => worldRenderer.World.Type != WorldType.Shellmap; @@ -74,8 +85,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic mouseControlDescModern.IsVisible = () => !gs.UseClassicMouseStyle; var mouseControlDropdown = widget.Get("MOUSE_CONTROL_DROPDOWN"); - mouseControlDropdown.OnMouseDown = _ => InputSettingsLogic.ShowMouseControlDropdown(mouseControlDropdown, gs); - mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; + mouseControlDropdown.OnMouseDown = _ => InputSettingsLogic.ShowMouseControlDropdown(modData, mouseControlDropdown, gs); + mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? classic : modern; foreach (var container in new[] { mouseControlDescClassic, mouseControlDescModern }) { @@ -113,8 +124,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var viewportSizes = modData.Manifest.Get(); var battlefieldCameraDropDown = widget.Get("BATTLEFIELD_CAMERA_DROPDOWN"); - var battlefieldCameraLabel = new CachedTransform(vs => DisplaySettingsLogic.ViewportSizeNames[vs]); - battlefieldCameraDropDown.OnMouseDown = _ => DisplaySettingsLogic.ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); + var battlefieldCameraLabel = new CachedTransform(vs => DisplaySettingsLogic.GetViewportSizeName(modData, vs)); + battlefieldCameraDropDown.OnMouseDown = _ => DisplaySettingsLogic.ShowBattlefieldCameraDropdown(modData, battlefieldCameraDropDown, viewportSizes, ds); battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); var uiScaleDropdown = widget.Get("UI_SCALE_DROPDOWN"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickClientLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickClientLogic.cs index b061cf53a4..77c7659e75 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickClientLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickClientLogic.cs @@ -16,10 +16,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic { class KickClientLogic : ChromeLogic { + [TranslationReference("player")] + static readonly string KickClient = "kick-client"; + [ObjectCreator.UseCtor] - public KickClientLogic(Widget widget, string clientName, Action okPressed, Action cancelPressed) + public KickClientLogic(ModData modData, Widget widget, string clientName, Action okPressed, Action cancelPressed) { - widget.Get("TITLE").GetText = () => $"Kick {clientName}?"; + var kickMessage = modData.Translation.GetString(KickClient, Translation.Arguments("player", clientName)); + widget.Get("TITLE").GetText = () => kickMessage; var tempBan = false; var preventRejoiningCheckbox = widget.Get("PREVENT_REJOINING_CHECKBOX"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickSpectatorsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickSpectatorsLogic.cs index 08a2dfbb04..69a4985d91 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickSpectatorsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/KickSpectatorsLogic.cs @@ -16,10 +16,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic { class KickSpectatorsLogic : ChromeLogic { + [TranslationReference("count")] + static readonly string KickSpectators = "kick-spectators"; + [ObjectCreator.UseCtor] - public KickSpectatorsLogic(Widget widget, int clientCount, Action okPressed, Action cancelPressed) + public KickSpectatorsLogic(ModData modData, Widget widget, int clientCount, Action okPressed, Action cancelPressed) { - widget.Get("TEXT").GetText = () => $"Are you sure you want to kick {clientCount} spectators?"; + var kickMessage = modData.Translation.GetString(KickSpectators, Translation.Arguments("count", clientCount)); + widget.Get("TEXT").GetText = () => kickMessage; widget.Get("OK_BUTTON").OnClick = () => { diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs index 08fd519a95..2e223b7141 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyLogic.cs @@ -47,7 +47,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ScrollPanelWidget lobbyChatPanel; readonly Dictionary chatTemplates = new Dictionary(); readonly TextFieldWidget chatTextField; - readonly CachedTransform chatDisabledLabel; + readonly CachedTransform chatAvailableIn; + readonly string chatDisabled; readonly ScrollPanelWidget players; @@ -74,6 +75,42 @@ namespace OpenRA.Mods.Common.Widgets.Logic bool MapIsPlayable => (mapStatus & Session.MapStatus.Playable) == Session.MapStatus.Playable; + [TranslationReference] + static readonly string Add = "add"; + + [TranslationReference] + static readonly string Remove = "remove"; + + [TranslationReference] + static readonly string ConfigureBots = "configure-bots"; + + [TranslationReference("count")] + static readonly string NumberTeams = "n-teams"; + + [TranslationReference] + static readonly string HumanVsBots = "humans-vs-bots"; + + [TranslationReference] + static readonly string FreeForAll = "free-for-all"; + + [TranslationReference] + static readonly string ConfigureTeams = "configure-teams"; + + [TranslationReference] + static readonly string Back = "back"; + + [TranslationReference] + static readonly string Team = "team"; + + [TranslationReference] + static readonly string All = "all"; + + [TranslationReference("seconds")] + static readonly string ChatAvailability = "chat-availability"; + + [TranslationReference] + static readonly string ChatDisabled = "chat-disabled"; + // Listen for connection failures void ConnectionStateChanged(OrderManager om, string password, NetworkConnection connection) { @@ -226,7 +263,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { new DropDownOption() { - Title = "Add", + Title = modData.Translation.GetString(Add), IsSelected = () => false, OnClick = () => { @@ -245,7 +282,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { botOptions.Add(new DropDownOption() { - Title = "Remove", + Title = modData.Translation.GetString(Remove), IsSelected = () => false, OnClick = () => { @@ -259,7 +296,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic }); } - options.Add("Configure Bots", botOptions); + options.Add(modData.Translation.GetString(ConfigureBots), botOptions); } var teamCount = (orderManager.LobbyInfo.Slots.Count(s => !s.Value.LockTeam && orderManager.LobbyInfo.ClientInSlot(s.Key) != null) + 1) / 2; @@ -267,7 +304,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var teamOptions = Enumerable.Range(2, teamCount - 1).Reverse().Select(d => new DropDownOption { - Title = $"{d} Teams", + Title = modData.Translation.GetString(NumberTeams, Translation.Arguments("count", d)), IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command($"assignteams {d}")) }).ToList(); @@ -276,7 +313,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { teamOptions.Add(new DropDownOption { - Title = "Humans vs Bots", + Title = modData.Translation.GetString(HumanVsBots), IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command("assignteams 1")) }); @@ -284,12 +321,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic teamOptions.Add(new DropDownOption { - Title = "Free for all", + Title = modData.Translation.GetString(FreeForAll), IsSelected = () => false, OnClick = () => orderManager.IssueOrder(Order.Command("assignteams 0")) }); - options.Add("Configure Teams", teamOptions); + options.Add(modData.Translation.GetString(ConfigureTeams), teamOptions); } Func setupItem = (option, template) => @@ -407,7 +444,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic disconnectButton.OnClick = () => { Ui.CloseWindow(); onExit(); }; if (skirmishMode) - disconnectButton.Text = "Back"; + disconnectButton.Text = modData.Translation.GetString(Back); if (logicArgs.TryGetValue("ChatTemplates", out var templateIds)) { @@ -419,7 +456,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic } var chatMode = lobby.Get("CHAT_MODE"); - chatMode.GetText = () => teamChat ? "Team" : "All"; + var team = modData.Translation.GetString(Team); + var all = modData.Translation.GetString(All); + chatMode.GetText = () => teamChat ? team : all; chatMode.OnClick = () => teamChat ^= true; chatMode.IsDisabled = () => disableTeamChat || !chatEnabled; @@ -459,7 +498,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic chatTextField.OnEscKey = _ => chatTextField.YieldKeyboardFocus(); - chatDisabledLabel = new CachedTransform(x => x > 0 ? $"Chat available in {x} seconds..." : "Chat Disabled"); + chatAvailableIn = new CachedTransform(x => modData.Translation.GetString(ChatAvailability, Translation.Arguments("seconds", x))); + chatDisabled = modData.Translation.GetString(ChatDisabled); lobbyChatPanel = lobby.Get("CHAT_DISPLAY"); lobbyChatPanel.RemoveChildren(); @@ -524,7 +564,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (TextNotificationsManager.ChatDisabledUntil != uint.MaxValue) remaining = (int)(TextNotificationsManager.ChatDisabledUntil - Game.RunTime + 999) / 1000; - chatTextField.Text = chatDisabledLabel.Update(remaining); + chatTextField.Text = remaining == 0 ? chatDisabled : chatAvailableIn.Update(remaining); } } @@ -612,9 +652,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic template = emptySlotTemplate.Clone(); if (isHost) - LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, map); + LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, map, modData); else - LobbyUtils.SetupSlotWidget(template, slot, client); + LobbyUtils.SetupSlotWidget(template, modData, slot, client); var join = template.Get("JOIN"); join.IsVisible = () => !slot.Closed; @@ -631,7 +671,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic LobbyUtils.SetupLatencyWidget(template, client, orderManager); if (client.Bot != null) - LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, map); + LobbyUtils.SetupEditableSlotWidget(template, slot, client, orderManager, map, modData); else LobbyUtils.SetupEditableNameWidget(template, client, orderManager, worldRenderer); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs index 3179291899..364af9c677 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyOptionsLogic.cs @@ -20,6 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class LobbyOptionsLogic : ChromeLogic { + readonly ModData modData; readonly ScrollPanelWidget panel; readonly Widget optionsContainer; readonly Widget checkboxRowTemplate; @@ -31,9 +32,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly Func configurationDisabled; MapPreview mapPreview; + [TranslationReference] + static readonly string NotAvailable = "not-available"; + [ObjectCreator.UseCtor] - internal LobbyOptionsLogic(Widget widget, OrderManager orderManager, Func getMap, Func configurationDisabled) + internal LobbyOptionsLogic(ModData modData, Widget widget, OrderManager orderManager, Func getMap, Func configurationDisabled) { + this.modData = modData; this.getMap = getMap; this.orderManager = orderManager; this.configurationDisabled = configurationDisabled; @@ -131,7 +136,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var getOptionLabel = new CachedTransform(id => { if (id == null || !option.Values.TryGetValue(id, out var value)) - return "Not Available"; + return modData.Translation.GetString(NotAvailable); return value; }); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs index 2e71cce572..1e235e416a 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/LobbyUtils.cs @@ -23,6 +23,21 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public static class LobbyUtils { + [TranslationReference] + static readonly string Open = "open"; + + [TranslationReference] + static readonly string Closed = "closed"; + + [TranslationReference] + static readonly string Bots = "bots"; + + [TranslationReference] + static readonly string BotsDisabled = "bots-disabled"; + + [TranslationReference] + static readonly string Slot = "slot"; + class SlotDropDownOption { public readonly string Title; @@ -38,15 +53,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic } public static void ShowSlotDropDown(DropDownButtonWidget dropdown, Session.Slot slot, - Session.Client client, OrderManager orderManager, MapPreview map) + Session.Client client, OrderManager orderManager, MapPreview map, ModData modData) { + var open = modData.Translation.GetString(Open); + var closed = modData.Translation.GetString(Closed); var options = new Dictionary> { { - "Slot", new List + modData.Translation.GetString(Slot), new List { - new SlotDropDownOption("Open", "slot_open " + slot.PlayerReference, () => !slot.Closed && client == null), - new SlotDropDownOption("Closed", "slot_close " + slot.PlayerReference, () => slot.Closed) + new SlotDropDownOption(open, "slot_open " + slot.PlayerReference, () => !slot.Closed && client == null), + new SlotDropDownOption(closed, "slot_close " + slot.PlayerReference, () => slot.Closed) } } }; @@ -63,7 +80,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } } - options.Add(bots.Count > 0 ? "Bots" : "Bots Disabled", bots); + options.Add(bots.Count > 0 ? Bots : BotsDisabled, bots); Func setupItem = (o, itemTemplate) => { @@ -436,7 +453,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } public static void SetupEditableSlotWidget(Widget parent, Session.Slot s, Session.Client c, - OrderManager orderManager, MapPreview map) + OrderManager orderManager, MapPreview map, ModData modData) { var slot = parent.Get("SLOT_OPTIONS"); slot.IsVisible = () => true; @@ -446,18 +463,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic WidgetUtils.TruncateText(name, slot.Bounds.Width - slot.Bounds.Height - slot.LeftMargin - slot.RightMargin, Game.Renderer.Fonts[slot.Font])); - slot.GetText = () => truncated.Update(c != null ? c.Name : s.Closed ? "Closed" : "Open"); - slot.OnMouseDown = _ => ShowSlotDropDown(slot, s, c, orderManager, map); + var closed = modData.Translation.GetString(Closed); + var open = modData.Translation.GetString(Open); + slot.GetText = () => truncated.Update(c != null ? c.Name : s.Closed ? closed : open); + slot.OnMouseDown = _ => ShowSlotDropDown(slot, s, c, orderManager, map, modData); // Ensure Name selector (if present) is hidden HideChildWidget(parent, "NAME"); } - public static void SetupSlotWidget(Widget parent, Session.Slot s, Session.Client c) + public static void SetupSlotWidget(Widget parent, ModData modData, Session.Slot s, Session.Client c) { var name = parent.Get("NAME"); name.IsVisible = () => true; - name.GetText = () => c != null ? c.Name : s.Closed ? "Closed" : "Open"; + name.GetText = () => c != null ? c.Name : s.Closed + ? modData.Translation.GetString(Closed) + : modData.Translation.GetString(Open); // Ensure Slot selector (if present) is hidden HideChildWidget(parent, "SLOT_OPTIONS"); diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/MapPreviewLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/MapPreviewLogic.cs index 932fe92c76..cc37a1c673 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/MapPreviewLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/MapPreviewLogic.cs @@ -23,6 +23,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic bool installHighlighted; int blinkTick; + [TranslationReference] + static readonly string Connecting = "connecting"; + + [TranslationReference("size")] + static readonly string Downloading = "downloading-map"; + + [TranslationReference("size", "progress")] + static readonly string DownloadingPercentage = "downloading-map-progress"; + + [TranslationReference] + static readonly string RetryInstall = "retry-install"; + + [TranslationReference] + static readonly string RetrySearch = "retry-search"; + + [TranslationReference("author")] + static readonly string CreatedBy = "created-by"; + [ObjectCreator.UseCtor] internal MapPreviewLogic(Widget widget, ModData modData, OrderManager orderManager, Func<(MapPreview Map, Session.MapStatus Status)> getMap, Action onMouseDown, Func> getSpawnOccupants, @@ -40,7 +58,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return map.Status == MapStatus.Available && isPlayable; }; - SetupWidgets(available, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); + SetupWidgets(available, modData, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); } var invalid = widget.GetOrNull("MAP_INVALID"); @@ -52,7 +70,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return map.Status == MapStatus.Available && (serverStatus & Session.MapStatus.Incompatible) != 0; }; - SetupWidgets(invalid, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); + SetupWidgets(invalid, modData, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); } var validating = widget.GetOrNull("MAP_VALIDATING"); @@ -64,7 +82,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return map.Status == MapStatus.Available && (serverStatus & Session.MapStatus.Validating) != 0; }; - SetupWidgets(validating, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); + SetupWidgets(validating, modData, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); } var download = widget.GetOrNull("MAP_DOWNLOADABLE"); @@ -72,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { download.IsVisible = () => getMap().Map.Status == MapStatus.DownloadAvailable; - SetupWidgets(download, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); + SetupWidgets(download, modData, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); var install = download.GetOrNull("MAP_INSTALL"); if (install != null) @@ -99,7 +117,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic return map.Status != MapStatus.Available && map.Status != MapStatus.DownloadAvailable; }; - SetupWidgets(progress, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); + SetupWidgets(progress, modData, getMap, onMouseDown, getSpawnOccupants, getDisabledSpawnPoints, showUnoccupiedSpawnpoints); var statusSearching = progress.GetOrNull("MAP_STATUS_SEARCHING"); if (statusSearching != null) @@ -134,13 +152,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var (map, _) = getMap(); if (map.DownloadBytes == 0) - return "Connecting..."; + return modData.Translation.GetString(Connecting); // Server does not provide the total file length if (map.DownloadPercentage == 0) - return $"Downloading {map.DownloadBytes / 1024} kB"; + modData.Translation.GetString(Downloading, Translation.Arguments("size", map.DownloadBytes / 1024)); - return $"Downloading {map.DownloadBytes / 1024} kB ({map.DownloadPercentage}%)"; + return modData.Translation.GetString(DownloadingPercentage, Translation.Arguments("size", map.DownloadBytes / 1024, "progress", map.DownloadPercentage)); }; } @@ -168,7 +186,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic modData.MapCache.QueryRemoteMapDetails(mapRepository, new[] { map.Uid }); }; - retry.GetText = () => getMap().Map.Status == MapStatus.DownloadError ? "Retry Install" : "Retry Search"; + retry.GetText = () => getMap().Map.Status == MapStatus.DownloadError + ? modData.Translation.GetString(RetryInstall) + : modData.Translation.GetString(RetrySearch); } var progressbar = progress.GetOrNull("MAP_PROGRESSBAR"); @@ -190,7 +210,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } } - void SetupWidgets(Widget parent, + static void SetupWidgets(Widget parent, ModData modData, Func<(MapPreview Map, Session.MapStatus Status)> getMap, Action onMouseDown, Func> getSpawnOccupants, @@ -235,7 +255,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var font = Game.Renderer.Fonts[authorLabel.Font]; var author = new CachedTransform( - m => WidgetUtils.TruncateText($"Created by {m.Author}", authorLabel.Bounds.Width, font)); + m => WidgetUtils.TruncateText(modData.Translation.GetString(CreatedBy, Translation.Arguments("author", m.Author)), authorLabel.Bounds.Width, font)); authorLabel.GetText = () => author.Update(getMap().Map); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/Lobby/SpawnSelectorTooltipLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Lobby/SpawnSelectorTooltipLogic.cs index 28b2621777..624cc4bb19 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Lobby/SpawnSelectorTooltipLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Lobby/SpawnSelectorTooltipLogic.cs @@ -17,8 +17,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class SpawnSelectorTooltipLogic : ChromeLogic { + [TranslationReference] + static readonly string DisabledSpawn = "disabled-spawn"; + + [TranslationReference] + static readonly string AvailableSpawn = "available-spawn"; + + [TranslationReference("team")] + static readonly string TeamNumber = "team-number"; + + readonly CachedTransform teamMessage; + [ObjectCreator.UseCtor] - public SpawnSelectorTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, MapPreviewWidget preview, bool showUnoccupiedSpawnpoints) + public SpawnSelectorTooltipLogic(Widget widget, ModData modData, TooltipContainerWidget tooltipContainer, MapPreviewWidget preview, bool showUnoccupiedSpawnpoints) { var showTooltip = true; widget.IsVisible = () => preview.TooltipSpawnIndex != -1 && showTooltip; @@ -36,6 +47,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic var labelText = ""; string playerFaction = null; var playerTeam = -1; + teamMessage = new CachedTransform(t => modData.Translation.GetString(TeamNumber, Translation.Arguments("team", t))); + var disabledSpawn = modData.Translation.GetString(DisabledSpawn); + var availableSpawn = modData.Translation.GetString(AvailableSpawn); tooltipContainer.BeforeRender = () => { @@ -58,7 +72,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic return; } - labelText = preview.DisabledSpawnPoints().Contains(preview.TooltipSpawnIndex) ? "Disabled spawn" : "Available spawn"; + labelText = preview.DisabledSpawnPoints().Contains(preview.TooltipSpawnIndex) + ? disabledSpawn + : availableSpawn; + playerFaction = null; playerTeam = 0; widget.Bounds.Height = singleHeight; @@ -75,7 +92,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic flag.IsVisible = () => playerFaction != null; flag.GetImageCollection = () => "flags"; flag.GetImageName = () => playerFaction; - team.GetText = () => $"Team {playerTeam}"; + team.GetText = () => teamMessage.Update(playerTeam); team.IsVisible = () => playerTeam > 0; } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs index a7d4244b79..2b51dd5648 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MainMenuLogic.cs @@ -31,6 +31,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly ScrollPanelWidget newsPanel; readonly Widget newsTemplate; readonly LabelWidget newsStatus; + readonly ModData modData; + + [TranslationReference] + static readonly string LoadingNews = "loading-news"; + + [TranslationReference("message")] + static readonly string NewsRetrivalFailed = "news-retrival-failed"; + + [TranslationReference("message")] + static readonly string NewsParsingFailed = "news-parsing-failed"; // Update news once per game launch static bool fetchedNews; @@ -52,6 +62,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic [ObjectCreator.UseCtor] public MainMenuLogic(Widget widget, World world, ModData modData) { + this.modData = modData; + rootMenu = widget; rootMenu.Get("VERSION_LABEL").Text = modData.Manifest.Metadata.Version; @@ -205,7 +217,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic newsPanel.RemoveChild(newsTemplate); newsStatus = newsPanel.Get("NEWS_STATUS"); - SetNewsStatus("Loading news"); + SetNewsStatus(modData.Translation.GetString(LoadingNews)); } Game.OnRemoteDirectConnect += OnRemoteDirectConnect; @@ -318,7 +330,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { Game.RunAfterTick(() => // run on the main thread { - SetNewsStatus($"Failed to retrieve news: {e.Message}"); + SetNewsStatus(modData.Translation.GetString(NewsRetrivalFailed, Translation.Arguments("message", e.Message))); }); } }); @@ -390,7 +402,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } catch (Exception ex) { - SetNewsStatus($"Failed to parse news: {ex.Message}"); + SetNewsStatus(modData.Translation.GetString(NewsParsingFailed, Translation.Arguments("message", ex.Message))); } return null; diff --git a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs index 82232df8fb..5a6afb7f9f 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MapChooserLogic.cs @@ -18,6 +18,52 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class MapChooserLogic : ChromeLogic { + [TranslationReference] + static readonly string AllMaps = "all-maps"; + readonly string allMaps; + + [TranslationReference] + static readonly string NoMatches = "no-matches"; + + [TranslationReference("players")] + static readonly string Players = "player-players"; + + [TranslationReference("author")] + static readonly string CreatedBy = "created-by"; + + [TranslationReference] + static readonly string MapSizeHuge = "map-size-huge"; + + [TranslationReference] + static readonly string MapSizeLarge = "map-size-large"; + + [TranslationReference] + static readonly string MapSizeMedium = "map-size-medium"; + + [TranslationReference] + static readonly string MapSizeSmall = "map-size-small"; + + [TranslationReference("map")] + static readonly string MapDeletionFailed = "map-deletion-failed"; + + [TranslationReference] + static readonly string DeleteMapTitle = "delete-map-title"; + + [TranslationReference("title")] + static readonly string DeleteMapPrompt = "delete-map-prompt"; + + [TranslationReference] + static readonly string DeleteMapAccept = "delete-map-accept"; + + [TranslationReference] + static readonly string DeleteAllMapsTitle = "delete-all-maps-title"; + + [TranslationReference] + static readonly string DeleteAllMapsPrompt = "delete-all-maps-prompt"; + + [TranslationReference] + static readonly string DeleteAllMapsAccept = "delete-all-maps-accept"; + readonly Widget widget; readonly DropDownButtonWidget gameModeDropdown; readonly ModData modData; @@ -43,6 +89,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.modData = modData; this.onSelect = onSelect; + allMaps = modData.Translation.GetString(AllMaps); + var approving = new Action(() => { Ui.CloseWindow(); @@ -192,7 +240,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic // 'all game types' extra item categories.Insert(0, (null as string, tabMaps[tab].Length)); - Func<(string Category, int Count), string> showItem = x => $"{x.Category ?? "All Maps"} ({x.Count})"; + Func<(string Category, int Count), string> showItem = x => (x.Category ?? allMaps) + $" ({x.Count})"; Func<(string Category, int Count), ScrollItemWidget, ScrollItemWidget> setupItem = (ii, template) => { @@ -210,7 +258,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { var item = categories.FirstOrDefault(m => m.Category == category); if (item == default((string, int))) - item.Category = "No matches"; + item.Category = modData.Translation.GetString(NoMatches); return showItem(item); }; @@ -269,25 +317,23 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (type != null) details = type + " "; - details += $"({preview.PlayerCount} players)"; + details += modData.Translation.GetString(Players, Translation.Arguments("players", preview.PlayerCount)); detailsWidget.GetText = () => details; } var authorWidget = item.GetOrNull("AUTHOR"); - if (authorWidget != null) - { - WidgetUtils.TruncateLabelToTooltip(authorWidget, $"Created by {preview.Author}"); - } + if (authorWidget != null && !string.IsNullOrEmpty(preview.Author)) + WidgetUtils.TruncateLabelToTooltip(authorWidget, modData.Translation.GetString(CreatedBy, Translation.Arguments("author", preview.Author))); var sizeWidget = item.GetOrNull("SIZE"); if (sizeWidget != null) { var size = preview.Bounds.Width + "x" + preview.Bounds.Height; var numberPlayableCells = preview.Bounds.Width * preview.Bounds.Height; - if (numberPlayableCells >= 120 * 120) size += " (Huge)"; - else if (numberPlayableCells >= 90 * 90) size += " (Large)"; - else if (numberPlayableCells >= 60 * 60) size += " (Medium)"; - else size += " (Small)"; + if (numberPlayableCells >= 120 * 120) size += " " + modData.Translation.GetString(MapSizeHuge); + else if (numberPlayableCells >= 90 * 90) size += " " + modData.Translation.GetString(MapSizeLarge); + else if (numberPlayableCells >= 60 * 60) size += " " + modData.Translation.GetString(MapSizeMedium); + else size += " " + modData.Translation.GetString(MapSizeSmall); sizeWidget.GetText = () => size; } @@ -315,7 +361,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } catch (Exception ex) { - TextNotificationsManager.Debug("Failed to delete map '{0}'. See the debug.log file for details.", map); + TextNotificationsManager.Debug(modData.Translation.GetString(MapDeletionFailed, Translation.Arguments("map", map))); Log.Write("debug", ex.ToString()); } @@ -324,23 +370,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic void DeleteOneMap(string map, Action after) { - ConfirmationDialogs.ButtonPrompt( - title: "Delete map", - text: $"Delete the map '{modData.MapCache[map].Title}'?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteMapTitle, + text: DeleteMapPrompt, + textArguments: Translation.Arguments("title", modData.MapCache[map].Title), onConfirm: () => { var newUid = DeleteMap(map); after?.Invoke(newUid); }, - confirmText: "Delete", + confirmText: DeleteMapAccept, onCancel: () => { }); } void DeleteAllMaps(string[] maps, Action after) { - ConfirmationDialogs.ButtonPrompt( - title: "Delete maps", - text: "Delete all maps on this page?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteAllMapsTitle, + text: DeleteAllMapsPrompt, onConfirm: () => { foreach (var map in maps) @@ -348,7 +395,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic after?.Invoke(Game.ModData.MapCache.ChooseInitialMap(null, Game.CosmeticRandom)); }, - confirmText: "Delete", + confirmText: DeleteAllMapsAccept, onCancel: () => { }); } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs index 689d6601d0..26d1c9a3b1 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MissionBrowserLogic.cs @@ -25,6 +25,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic { enum PlayingVideo { None, Info, Briefing, GameStart } + [TranslationReference] + static readonly string NoVideoTitle = "no-video-title"; + + [TranslationReference] + static readonly string NoVideoText = "no-video-text"; + + [TranslationReference] + static readonly string NoVideoCancel = "no-video-cancel"; + + [TranslationReference] + static readonly string CantPlayTitle = "cant-play-title"; + + [TranslationReference] + static readonly string CantPlayPrompt = "cant-play-prompt"; + + [TranslationReference] + static readonly string CantPlayCancel = "cant-play-cancel"; + readonly ModData modData; readonly Action onStart; readonly ScrollPanelWidget descriptionPanel; @@ -330,10 +348,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic { if (!modData.DefaultFileSystem.Exists(video)) { - ConfirmationDialogs.ButtonPrompt( - title: "Video not installed", - text: "The game videos can be installed from the\n\"Manage Content\" menu in the mod chooser.", - cancelText: "Back", + ConfirmationDialogs.ButtonPrompt(modData, + title: NoVideoTitle, + text: NoVideoText, + cancelText: NoVideoCancel, onCancel: () => { }); } else @@ -347,10 +365,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic { StopVideo(player); - ConfirmationDialogs.ButtonPrompt( - title: "Unable to play video", - text: "Something went wrong during video playback.", - cancelText: "Back", + ConfirmationDialogs.ButtonPrompt(modData, + title: CantPlayTitle, + text: CantPlayPrompt, + cancelText: CantPlayCancel, onCancel: () => { }); } else diff --git a/OpenRA.Mods.Common/Widgets/Logic/MusicPlayerLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MusicPlayerLogic.cs index 561a7fc9b0..f64497d1db 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MusicPlayerLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MusicPlayerLogic.cs @@ -18,6 +18,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class MusicPlayerLogic : ChromeLogic { + [TranslationReference] + static readonly string SoundMuted = "sound-muted"; + + [TranslationReference] + static readonly string NoSongPlaying = "no-song-playing"; + readonly ScrollPanelWidget musicList; readonly ScrollItemWidget itemTemplate; @@ -25,7 +31,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic MusicInfo currentSong = null; [ObjectCreator.UseCtor] - public MusicPlayerLogic(Widget widget, World world, Action onExit) + public MusicPlayerLogic(Widget widget, World world, ModData modData, Action onExit) { var panel = widget; @@ -43,7 +49,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic panel.Get("MUTE_LABEL").GetText = () => { if (Game.Settings.Sound.Mute) - return "Audio has been muted in settings."; + return modData.Translation.GetString(SoundMuted); return ""; }; @@ -95,9 +101,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic return $"{minutes:D2}:{seconds:D2} / {totalMinutes:D2}:{totalSeconds:D2}"; }; + var noSongPlaying = modData.Translation.GetString(NoSongPlaying); var musicTitle = panel.GetOrNull("TITLE_LABEL"); if (musicTitle != null) - musicTitle.GetText = () => currentSong != null ? currentSong.Title : "No song playing"; + musicTitle.GetText = () => currentSong != null ? currentSong.Title : noSongPlaying; var musicSlider = panel.Get("MUSIC_SLIDER"); musicSlider.OnChange += x => Game.Sound.MusicVolume = x; diff --git a/OpenRA.Mods.Common/Widgets/Logic/MuteHotkeyLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/MuteHotkeyLogic.cs index 1277adc626..26ee22b321 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/MuteHotkeyLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/MuteHotkeyLogic.cs @@ -18,9 +18,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic [ChromeLogicArgsHotkeys("MuteAudioKey")] public class MuteHotkeyLogic : SingleHotkeyBaseLogic { + readonly ModData modData; + + [TranslationReference] + static readonly string AudioMuted = "audio-muted"; + + [TranslationReference] + static readonly string AudioUnmuted = "audio-unmuted"; + [ObjectCreator.UseCtor] public MuteHotkeyLogic(Widget widget, ModData modData, Dictionary logicArgs) - : base(widget, modData, "MuteAudioKey", "GLOBAL_KEYHANDLER", logicArgs) { } + : base(widget, modData, "MuteAudioKey", "GLOBAL_KEYHANDLER", logicArgs) + { + this.modData = modData; + } protected override bool OnHotkeyActivated(KeyInput e) { @@ -29,12 +40,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (Game.Settings.Sound.Mute) { Game.Sound.MuteAudio(); - TextNotificationsManager.AddFeedbackLine("Audio muted."); + TextNotificationsManager.AddFeedbackLine(modData.Translation.GetString(AudioMuted)); } else { Game.Sound.UnmuteAudio(); - TextNotificationsManager.AddFeedbackLine("Audio unmuted."); + TextNotificationsManager.AddFeedbackLine(modData.Translation.GetString(AudioUnmuted)); } return true; diff --git a/OpenRA.Mods.Common/Widgets/Logic/PlayerProfileLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/PlayerProfileLogic.cs index b4a29ef839..b9d77f8bc1 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/PlayerProfileLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/PlayerProfileLogic.cs @@ -131,6 +131,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic public class RegisteredProfileTooltipLogic : ChromeLogic { + [TranslationReference] + static readonly string LoadingPlayerProfile = "loading-player-profile"; + + [TranslationReference] + static readonly string LoadingPlayerProfileFailed = "loading-player-profile-failed"; + readonly PlayerDatabase playerDatabase; PlayerProfile profile; bool profileLoaded; @@ -154,7 +160,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var profileWidth = 0; var maxProfileWidth = widget.Bounds.Width; - var messageText = "Loading player profile..."; + var messageText = modData.Translation.GetString(LoadingPlayerProfile); var messageWidth = messageFont.Measure(messageText).X + 2 * message.Bounds.Left; Task.Run(async () => @@ -243,7 +249,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic { if (profile == null) { - messageText = "Failed to load player profile."; + messageText = modData.Translation.GetString(LoadingPlayerProfileFailed); messageWidth = messageFont.Measure(messageText).X + 2 * message.Bounds.Left; header.Bounds.Width = widget.Bounds.Width = messageWidth; } diff --git a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs index 5032a98ad4..78ddc44498 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ReplayBrowserLogic.cs @@ -25,6 +25,78 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class ReplayBrowserLogic : ChromeLogic { + [TranslationReference("time")] + static readonly string Duration = "duration"; + + [TranslationReference] + static readonly string Singleplayer = "singleplayer"; + + [TranslationReference] + static readonly string Multiplayer = "multiplayer"; + + [TranslationReference] + static readonly string Today = "today"; + + [TranslationReference] + static readonly string LastWeek = "last-week"; + + [TranslationReference] + static readonly string LastFortnight = "last-fortnight"; + + [TranslationReference] + static readonly string LastMonth = "last-month"; + + [TranslationReference] + static readonly string ReplayDurationVeryShort = "replay-duration-very-short"; + + [TranslationReference] + static readonly string ReplayDurationShort = "replay-duration-short"; + + [TranslationReference] + static readonly string ReplayDurationMedium = "replay-duration-medium"; + + [TranslationReference] + static readonly string ReplayDurationLong = "replay-duration-long"; + + [TranslationReference] + static readonly string RenameReplayTitle = "rename-replay-title"; + + [TranslationReference] + static readonly string RenameReplayPrompt = "rename-replay-prompt"; + + [TranslationReference] + static readonly string RenameReplayAccept = "rename-replay-accept"; + + [TranslationReference] + static readonly string DeleteReplayTitle = "delete-replay-title"; + + [TranslationReference("replay")] + static readonly string DeleteReplayPrompt = "delete-replay-prompt"; + + [TranslationReference] + static readonly string DeleteReplayAccept = "delete-replay-accept"; + + [TranslationReference] + static readonly string DeleteAllReplaysTitle = "delete-all-replays-title"; + + [TranslationReference("count")] + static readonly string DeleteAllReplaysPrompt = "delete-all-replays-prompt"; + + [TranslationReference] + static readonly string DeleteAllReplaysAccept = "delete-all-replays-accept"; + + [TranslationReference("file")] + static readonly string ReplayDeletionFailed = "replay-deletion-failed"; + + [TranslationReference] + static readonly string Players = "players"; + + [TranslationReference("team")] + static readonly string TeamNumber = "team-number"; + + [TranslationReference] + static readonly string NoTeam = "no-team"; + static Filter filter = new Filter(); readonly Widget panel; @@ -101,7 +173,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic }); var replayDuration = new CachedTransform(r => - $"Duration: {WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds)}"); + modData.Translation.GetString(Duration, Translation.Arguments("time", WidgetUtils.FormatTimeSeconds((int)selectedReplay.GameInfo.Duration.TotalSeconds)))); panel.Get("DURATION").GetText = () => replayDuration.Update(selectedReplay); SetupFilters(); @@ -153,8 +225,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic var options = new List<(GameType GameType, string Text)> { (GameType.Any, ddb.GetText()), - (GameType.Singleplayer, "Singleplayer"), - (GameType.Multiplayer, "Multiplayer") + (GameType.Singleplayer, modData.Translation.GetString(Singleplayer)), + (GameType.Multiplayer, modData.Translation.GetString(Multiplayer)) }; var lookup = options.ToDictionary(kvp => kvp.GameType, kvp => kvp.Text); @@ -186,10 +258,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var options = new List<(DateType DateType, string Text)> { (DateType.Any, ddb.GetText()), - (DateType.Today, "Today"), - (DateType.LastWeek, "Last 7 days"), - (DateType.LastFortnight, "Last 14 days"), - (DateType.LastMonth, "Last 30 days") + (DateType.Today, modData.Translation.GetString(Today)), + (DateType.LastWeek, modData.Translation.GetString(LastWeek)), + (DateType.LastFortnight, modData.Translation.GetString(LastFortnight)), + (DateType.LastMonth, modData.Translation.GetString(LastMonth)) }; var lookup = options.ToDictionary(kvp => kvp.DateType, kvp => kvp.Text); @@ -222,10 +294,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var options = new List<(DurationType DurationType, string Text)> { (DurationType.Any, ddb.GetText()), - (DurationType.VeryShort, "Under 5 min"), - (DurationType.Short, "Short (10 min)"), - (DurationType.Medium, "Medium (30 min)"), - (DurationType.Long, "Long (60+ min)") + (DurationType.VeryShort, modData.Translation.GetString(ReplayDurationVeryShort)), + (DurationType.Short, modData.Translation.GetString(ReplayDurationShort)), + (DurationType.Medium, modData.Translation.GetString(ReplayDurationMedium)), + (DurationType.Long, modData.Translation.GetString(ReplayDurationLong)) }; var lookup = options.ToDictionary(kvp => kvp.DurationType, kvp => kvp.Text); @@ -393,13 +465,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic var directoryName = Path.GetDirectoryName(r.FilePath); var invalidChars = Path.GetInvalidFileNameChars(); - ConfirmationDialogs.TextInputPrompt( - "Rename Replay", - "Enter a new file name:", + ConfirmationDialogs.TextInputPrompt(modData, + RenameReplayTitle, + RenameReplayPrompt, initialName, onAccept: newName => RenameReplay(r, newName), onCancel: null, - acceptText: "Rename", + acceptText: RenameReplayAccept, cancelText: null, inputValidator: newName => { @@ -421,15 +493,16 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action onDeleteReplay = (r, after) => { - ConfirmationDialogs.ButtonPrompt( - title: "Delete selected replay?", - text: $"Delete replay '{Path.GetFileNameWithoutExtension(r.FilePath)}'?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteReplayTitle, + text: DeleteReplayPrompt, + textArguments: Translation.Arguments("replay", Path.GetFileNameWithoutExtension(r.FilePath)), onConfirm: () => { DeleteReplay(r); after?.Invoke(); }, - confirmText: "Delete", + confirmText: DeleteReplayAccept, onCancel: () => { }); }; @@ -458,9 +531,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic return; } - ConfirmationDialogs.ButtonPrompt( - title: "Delete all selected replays?", - text: $"Delete {list.Count} replays?", + ConfirmationDialogs.ButtonPrompt(modData, + title: DeleteAllReplaysTitle, + text: DeleteAllReplaysPrompt, + textArguments: Translation.Arguments("count", list.Count), onConfirm: () => { foreach (var replayMetadata in list) @@ -469,7 +543,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (selectedReplay == null) SelectFirstVisibleReplay(); }, - confirmText: "Delete All", + confirmText: DeleteAllReplaysAccept, onCancel: () => { }); }; } @@ -500,7 +574,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic } catch (Exception ex) { - TextNotificationsManager.Debug("Failed to delete replay file '{0}'. See the logs for details.", replay.FilePath); + TextNotificationsManager.Debug(modData.Translation.GetString(ReplayDeletionFailed, Translation.Arguments("file", replay.FilePath))); Log.Write("debug", ex.ToString()); return; } @@ -636,7 +710,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic var noTeams = players.Count() == 1; foreach (var p in players) { - var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : $"Team {p.Key}"; + var label = noTeams ? modData.Translation.GetString(Players) : p.Key > 0 + ? modData.Translation.GetString(TeamNumber, Translation.Arguments("team", p.Key)) + : modData.Translation.GetString(NoTeam); + teams.Add(label, p); } @@ -685,7 +762,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic void WatchReplay() { - if (selectedReplay != null && ReplayUtils.PromptConfirmReplayCompatibility(selectedReplay)) + if (selectedReplay != null && ReplayUtils.PromptConfirmReplayCompatibility(selectedReplay, modData)) { cancelLoadingReplays = true; diff --git a/OpenRA.Mods.Common/Widgets/Logic/ReplayUtils.cs b/OpenRA.Mods.Common/Widgets/Logic/ReplayUtils.cs index ad97013934..b473e97a1b 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ReplayUtils.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ReplayUtils.cs @@ -10,52 +10,72 @@ #endregion using System; +using System.Collections.Generic; using OpenRA.FileFormats; namespace OpenRA.Mods.Common.Widgets.Logic { public static class ReplayUtils { + [TranslationReference] + static readonly string IncompatibleReplayTitle = "incompatible-replay-title"; + + [TranslationReference] + static readonly string IncompatibleReplayPrompt = "incompatible-replay-prompt"; + + [TranslationReference("version")] + static readonly string UnknownVersion = "incompatible-replay-unknown-version"; + + [TranslationReference("mod")] + static readonly string UnknownMod = "incompatible-replay-unknown-mod"; + + [TranslationReference("mod")] + static readonly string UnvailableMod = "incompatible-replay-unavailable-mod"; + + [TranslationReference("version")] + static readonly string IncompatibleVersion = "incompatible-replay-incompatible-version"; + + [TranslationReference("map")] + static readonly string UnvailableMap = "incompatible-replay-unavailable-map"; + static readonly Action DoNothing = () => { }; - public static bool PromptConfirmReplayCompatibility(ReplayMetadata replayMeta, Action onCancel = null) + public static bool PromptConfirmReplayCompatibility(ReplayMetadata replayMeta, ModData modData, Action onCancel = null) { if (onCancel == null) onCancel = DoNothing; if (replayMeta == null) { - ConfirmationDialogs.ButtonPrompt("Incompatible Replay", "Replay metadata could not be read.", onCancel: onCancel); + ConfirmationDialogs.ButtonPrompt(modData, IncompatibleReplayTitle, + IncompatibleReplayPrompt, onCancel: onCancel); + return false; } var version = replayMeta.GameInfo.Version; if (version == null) - return IncompatibleReplayDialog("unknown version", version, onCancel); + return IncompatibleReplayDialog(UnknownVersion, Translation.Arguments("version", version), modData, onCancel); var mod = replayMeta.GameInfo.Mod; if (mod == null) - return IncompatibleReplayDialog("unknown mod", mod, onCancel); + return IncompatibleReplayDialog(UnknownMod, Translation.Arguments("mod", mod), modData, onCancel); if (!Game.Mods.ContainsKey(mod)) - return IncompatibleReplayDialog("unavailable mod", mod, onCancel); + return IncompatibleReplayDialog(UnvailableMod, Translation.Arguments("mod", mod), modData, onCancel); if (Game.Mods[mod].Metadata.Version != version) - return IncompatibleReplayDialog("incompatible version", version, onCancel); + return IncompatibleReplayDialog(IncompatibleVersion, Translation.Arguments("version", version), modData, onCancel); if (replayMeta.GameInfo.MapPreview.Status != MapStatus.Available) - return IncompatibleReplayDialog("unavailable map", replayMeta.GameInfo.MapUid, onCancel); + return IncompatibleReplayDialog(UnvailableMap, Translation.Arguments("map", replayMeta.GameInfo.MapUid), modData, onCancel); return true; } - static bool IncompatibleReplayDialog(string type, string name, Action onCancel) + static bool IncompatibleReplayDialog(string text, Dictionary textArguments, ModData modData, Action onCancel) { - var error = "It was recorded with an " + type; - error += string.IsNullOrEmpty(name) ? "." : $":\n{name}"; - - ConfirmationDialogs.ButtonPrompt("Incompatible Replay", error, onCancel: onCancel); - + ConfirmationDialogs.ButtonPrompt(modData, IncompatibleReplayTitle, text, textArguments: textArguments, onCancel: onCancel); return false; } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs index 7930d1767c..a1a49917f9 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ServerCreationLogic.cs @@ -19,7 +19,41 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class ServerCreationLogic : ChromeLogic { + [TranslationReference] + static readonly string InternetServerNatA = "internet-server-nat-A"; + + [TranslationReference] + static readonly string InternetServerNatBenabled = "internet-server-nat-B-enabled"; + + [TranslationReference] + static readonly string InternetServerNatBnotSupported = "internet-server-nat-B-not-supported"; + + [TranslationReference] + static readonly string InternetServerNatBdisabled = "internet-server-nat-B-disabled"; + + [TranslationReference] + static readonly string InternetServerNatC = "internet-server-nat-C"; + + [TranslationReference] + static readonly string LocalServer = "local-server"; + + [TranslationReference("port")] + static readonly string ServerCreationFailedPrompt = "server-creation-failed-prompt"; + + [TranslationReference] + static readonly string ServerCreationFailedPortUsed = "server-creation-failed-port-used"; + + [TranslationReference("message", "code")] + static readonly string ServerCreationFailedError = "server-creation-failed-error"; + + [TranslationReference] + static readonly string ServerCreationFailedTitle = "server-creation-failed-title"; + + [TranslationReference] + static readonly string ServerCreationFailedCancel = "server-creation-failed-cancel"; + readonly Widget panel; + readonly ModData modData; readonly LabelWidget noticesLabelA, noticesLabelB, noticesLabelC; readonly Action onCreate; readonly Action onExit; @@ -30,6 +64,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic public ServerCreationLogic(Widget widget, ModData modData, Action onExit, Action openLobby) { panel = widget; + this.modData = modData; onCreate = openLobby; this.onExit = onExit; @@ -154,12 +189,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (advertiseOnline) { - noticesLabelA.Text = "Internet Server (UPnP/NAT-PMP "; + noticesLabelA.Text = modData.Translation.GetString(InternetServerNatA) + " "; var aWidth = Game.Renderer.Fonts[noticesLabelA.Font].Measure(noticesLabelA.Text).X; noticesLabelA.Bounds.Width = aWidth; - noticesLabelB.Text = Nat.Status == NatStatus.Enabled ? "Enabled" : - Nat.Status == NatStatus.NotSupported ? "Not Supported" : "Disabled"; + noticesLabelB.Text = Nat.Status == NatStatus.Enabled ? modData.Translation.GetString(InternetServerNatBenabled) : + Nat.Status == NatStatus.NotSupported ? modData.Translation.GetString(InternetServerNatBnotSupported) + : modData.Translation.GetString(InternetServerNatBdisabled); noticesLabelB.TextColor = Nat.Status == NatStatus.Enabled ? ChromeMetrics.Get("NoticeSuccessColor") : Nat.Status == NatStatus.NotSupported ? ChromeMetrics.Get("NoticeErrorColor") : @@ -170,13 +206,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic noticesLabelB.Bounds.Width = bWidth; noticesLabelB.Visible = true; - noticesLabelC.Text = "):"; + noticesLabelC.Text = modData.Translation.GetString(InternetServerNatC); noticesLabelC.Bounds.X = noticesLabelB.Bounds.Right; noticesLabelC.Visible = true; } else { - noticesLabelA.Text = "Local Server:"; + noticesLabelA.Text = modData.Translation.GetString(LocalServer); noticesLabelB.Visible = false; noticesLabelC.Visible = false; } @@ -212,15 +248,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic } catch (System.Net.Sockets.SocketException e) { - var message = $"Could not listen on port {Game.Settings.Server.ListenPort}."; + var message = modData.Translation.GetString(ServerCreationFailedPrompt, Translation.Arguments("port", Game.Settings.Server.ListenPort)); // AddressAlreadyInUse (WSAEADDRINUSE) if (e.ErrorCode == 10048) - message += "\nCheck if the port is already being used."; + message += "\n" + modData.Translation.GetString(ServerCreationFailedPortUsed); else - message += $"\nError is: \"{e.Message}\" ({e.ErrorCode})"; + message += $"\n" + modData.Translation.GetString(ServerCreationFailedError, + Translation.Arguments("message", e.Message, "code", e.ErrorCode)); - ConfirmationDialogs.ButtonPrompt("Server Creation Failed", message, onCancel: () => { }, cancelText: "Back"); + ConfirmationDialogs.ButtonPrompt(modData, ServerCreationFailedTitle, message, + onCancel: () => { }, cancelText: ServerCreationFailedCancel); } } } diff --git a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs index b806552550..b15c04b57a 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/ServerListLogic.cs @@ -25,6 +25,74 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class ServerListLogic : ChromeLogic { + [TranslationReference] + static readonly string SearchStatusFailed = "search-status-failed"; + + [TranslationReference] + static readonly string SearchStatusNoGames = "search-status-no-games"; + + [TranslationReference("players")] + static readonly string PlayersOnline = "players-online"; + + [TranslationReference] + static readonly string NoServerSelected = "no-server-selected"; + readonly string noServerSelected; + + [TranslationReference] + static readonly string MapStatusSearching = "map-status-searching"; + readonly string mapStatusSearching; + + [TranslationReference] + static readonly string MapClassificationUnknown = "map-classification-unknown"; + readonly string mapClassificationUnknown; + + [TranslationReference("players")] + static readonly string PlayersLabel = "players-label"; + + [TranslationReference("bots")] + static readonly string BotsLabel = "bots-label"; + + [TranslationReference("spectators")] + static readonly string SpectatorsLabel = "spectators-label"; + + [TranslationReference] + static readonly string Players = "players"; + + [TranslationReference("team")] + static readonly string TeamNumber = "team-number"; + + [TranslationReference] + static readonly string NoTeam = "no-team"; + + [TranslationReference] + static readonly string Spectators = "spectators"; + + [TranslationReference("players")] + static readonly string OtherPlayers = "n-other-players"; + + [TranslationReference] + static readonly string Playing = "playing"; + readonly string playing; + + [TranslationReference] + static readonly string Waiting = "waiting"; + readonly string waiting; + + [TranslationReference("minutes")] + static readonly string InProgress = "in-progress-for"; + + [TranslationReference] + static readonly string PasswordProtected = "password-protected"; + + [TranslationReference] + static readonly string WaitingForPlayers = "waiting-for-players"; + + [TranslationReference] + static readonly string ServerShuttingDown = "server-shutting-down"; + + [TranslationReference] + static readonly string UnknownServerState = "unknown-server-state"; + readonly Color incompatibleVersionColor; readonly Color incompatibleProtectedGameColor; readonly Color protectedGameColor; @@ -62,12 +130,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic bool activeQuery; IEnumerable lanGameLocations; + readonly CachedTransform players; + readonly CachedTransform bots; + readonly CachedTransform spectators; + + readonly CachedTransform minutes; + readonly string passwordProtected; + readonly string waitingForPlayers; + readonly string serverShuttingDown; + readonly string unknownServerState; + public string ProgressLabelText() { switch (searchStatus) { - case SearchStatus.Failed: return "Failed to query server list."; - case SearchStatus.NoGames: return "No games found. Try changing filters."; + case SearchStatus.Failed: return modData.Translation.GetString(SearchStatusFailed); + case SearchStatus.NoGames: return modData.Translation.GetString(SearchStatusNoGames); default: return ""; } } @@ -78,6 +156,23 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.modData = modData; this.onJoin = onJoin; + playing = modData.Translation.GetString(Playing); + waiting = modData.Translation.GetString(Waiting); + + noServerSelected = modData.Translation.GetString(NoServerSelected); + mapStatusSearching = modData.Translation.GetString(MapStatusSearching); + mapClassificationUnknown = modData.Translation.GetString(MapClassificationUnknown); + + players = new CachedTransform(i => modData.Translation.GetString(PlayersLabel, Translation.Arguments("players", i))); + bots = new CachedTransform(i => modData.Translation.GetString(BotsLabel, Translation.Arguments("bots", i))); + spectators = new CachedTransform(i => modData.Translation.GetString(SpectatorsLabel, Translation.Arguments("spectators", i))); + + minutes = new CachedTransform(i => modData.Translation.GetString(InProgress, Translation.Arguments("minutes", i))); + passwordProtected = modData.Translation.GetString(PasswordProtected); + waitingForPlayers = modData.Translation.GetString(WaitingForPlayers); + serverShuttingDown = modData.Translation.GetString(ServerShuttingDown); + unknownServerState = modData.Translation.GetString(UnknownServerState); + services = modData.Manifest.Get(); incompatibleVersionColor = ChromeMetrics.Get("IncompatibleVersionColor"); @@ -222,7 +317,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var playersLabel = widget.GetOrNull("PLAYER_COUNT"); if (playersLabel != null) { - var playersText = new CachedTransform(c => c == 1 ? "1 Player Online" : c.ToString() + " Players Online"); + var playersText = new CachedTransform(p => modData.Translation.GetString(PlayersOnline, Translation.Arguments("players", p))); playersLabel.IsVisible = () => playerCount != 0; playersLabel.GetText = () => playersText.Update(playerCount); } @@ -250,13 +345,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic mapTitle.GetText = () => { if (currentMap == null) - return "No Server Selected"; + return noServerSelected; if (currentMap.Status == MapStatus.Searching) - return "Searching..."; + return mapStatusSearching; if (currentMap.Class == MapClassification.Unknown) - return "Unknown Map"; + return mapClassificationUnknown; return title.Update(currentMap); }; @@ -288,11 +383,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic modVersion.GetText = () => version.Update(currentServer); } - var players = widget.GetOrNull("SELECTED_PLAYERS"); - if (players != null) + var selectedPlayers = widget.GetOrNull("SELECTED_PLAYERS"); + if (selectedPlayers != null) { - players.IsVisible = () => currentServer != null && (clientContainer == null || currentServer.Clients.Length == 0); - players.GetText = () => PlayersLabel(currentServer); + selectedPlayers.IsVisible = () => currentServer != null && (clientContainer == null || currentServer.Clients.Length == 0); + selectedPlayers.GetText = () => PlayerLabel(currentServer); } clientContainer = widget.GetOrNull("CLIENT_LIST_CONTAINER"); @@ -320,9 +415,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic RefreshServerList(); } - static string PlayersLabel(GameServer game) + string PlayerLabel(GameServer game) { - return $"{(game.Players > 0 ? game.Players.ToString() : "No")} Player{(game.Players != 1 ? "s" : "")}{(game.Bots > 0 ? $", {game.Bots} Bot{(game.Bots != 1 ? "s" : "")}" : "")}{(game.Spectators > 0 ? $", {game.Spectators} Spectator{(game.Spectators != 1 ? "s" : "")}" : "")}"; + return players.Update(game.Players) + + bots.Update(game.Bots) + + spectators.Update(game.Spectators); } public void RefreshServerList() @@ -474,12 +571,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic var noTeams = players.Count() == 1; foreach (var p in players) { - var label = noTeams ? "Players" : p.Key == 0 ? "No Team" : $"Team {p.Key}"; + var label = noTeams ? modData.Translation.GetString(Players) : p.Key > 0 + ? modData.Translation.GetString(TeamNumber, Translation.Arguments("team", p.Key)) + : modData.Translation.GetString(NoTeam); teams.Add(label, p); } if (server.Clients.Any(c => c.IsSpectator)) - teams.Add("Spectators", server.Clients.Where(c => c.IsSpectator)); + teams.Add(modData.Translation.GetString(Spectators), server.Clients.Where(c => c.IsSpectator)); var factionInfo = modData.DefaultRules.Actors[SystemActors.World].TraitInfos(); foreach (var kv in teams) @@ -655,7 +754,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (game.Clients.Length > 10) displayClients = displayClients .Take(9) - .Append($"+ {game.Clients.Length - 9} other players"); + .Append(modData.Translation.GetString(OtherPlayers, Translation.Arguments("players", game.Clients.Length - 9))); var tooltip = displayClients.JoinWith("\n"); players.GetTooltipText = () => tooltip; @@ -667,8 +766,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic var state = item.GetOrNull("STATUS"); if (state != null) { - var label = game.State >= (int)ServerState.GameStarted ? - "Playing" : "Waiting"; + var label = game.State >= (int)ServerState.GameStarted ? playing : waiting; state.GetText = () => label; var color = GetStateColor(game, state, !canJoin); @@ -695,31 +793,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic return rows; } - static string GetStateLabel(GameServer game) + string GetStateLabel(GameServer game) { if (game == null) - return ""; + return string.Empty; if (game.State == (int)ServerState.GameStarted) { - var label = "In progress"; - - if (game.PlayTime > 0) - { - var totalMinutes = Math.Ceiling(game.PlayTime / 60.0); - label += $" for {totalMinutes} minute{(totalMinutes > 1 ? "s" : "")}"; - } - - return label; + var totalMinutes = Math.Ceiling(game.PlayTime / 60.0); + return minutes.Update(totalMinutes); } if (game.State == (int)ServerState.WaitingPlayers) - return game.Protected ? "Password protected" : "Waiting for players"; + return game.Protected ? passwordProtected : waitingForPlayers; if (game.State == (int)ServerState.ShuttingDown) - return "Server shutting down"; + return serverShuttingDown; - return "Unknown server state"; + return unknownServerState; } Color GetStateColor(GameServer game, LabelWidget label, bool darkened = false) diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs index cefe0740b1..0cfd23153c 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/DisplaySettingsLogic.cs @@ -22,6 +22,50 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class DisplaySettingsLogic : ChromeLogic { + [TranslationReference] + static readonly string Close = "close"; + + [TranslationReference] + static readonly string Medium = "medium"; + + [TranslationReference] + static readonly string Far = "far"; + + [TranslationReference] + static readonly string Furthest = "furthest"; + + [TranslationReference] + static readonly string Windowed = "windowed"; + + [TranslationReference] + static readonly string LegacyFullscreen = "legacy-fullscreen"; + readonly string legacyFullscreen; + + [TranslationReference] + static readonly string Fullscreen = "fullscreen"; + readonly string fullscreen; + + [TranslationReference("number")] + static readonly string Display = "display"; + + [TranslationReference] + static readonly string Standard = "standard"; + + [TranslationReference] + static readonly string ShowOnDamage = "show-on-damage"; + + [TranslationReference] + static readonly string AlwaysShow = "always-show"; + + [TranslationReference] + static readonly string Automatic = "automatic"; + + [TranslationReference] + static readonly string Manual = "manual"; + + [TranslationReference] + static readonly string Disabled = "disabled"; + static readonly int OriginalVideoDisplay; static readonly WindowMode OriginalGraphicsMode; static readonly int2 OriginalGraphicsWindowedSize; @@ -32,6 +76,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic readonly WorldRenderer worldRenderer; readonly WorldViewportSizes viewportSizes; + readonly string showOnDamage; + readonly string alwaysShow; + + readonly string automatic; + readonly string manual; + readonly string disabled; + static DisplaySettingsLogic() { var original = Game.Settings; @@ -49,16 +100,35 @@ namespace OpenRA.Mods.Common.Widgets.Logic this.modData = modData; viewportSizes = modData.Manifest.Get(); + legacyFullscreen = modData.Translation.GetString(LegacyFullscreen); + fullscreen = modData.Translation.GetString(Fullscreen); + registerPanel(panelID, label, InitPanel, ResetPanel); + + showOnDamage = modData.Translation.GetString(ShowOnDamage); + alwaysShow = modData.Translation.GetString(AlwaysShow); + + automatic = modData.Translation.GetString(Automatic); + manual = modData.Translation.GetString(Manual); + disabled = modData.Translation.GetString(Disabled); } - public static readonly Dictionary ViewportSizeNames = new Dictionary() + public static string GetViewportSizeName(ModData modData, WorldViewport worldViewport) { - { WorldViewport.Close, "Close" }, - { WorldViewport.Medium, "Medium" }, - { WorldViewport.Far, "Far" }, - { WorldViewport.Native, "Furthest" } - }; + switch (worldViewport) + { + case WorldViewport.Close: + return modData.Translation.GetString(Close); + case WorldViewport.Medium: + return modData.Translation.GetString(Medium); + case WorldViewport.Far: + return modData.Translation.GetString(Far); + case WorldViewport.Native: + return modData.Translation.GetString(Furthest); + default: + return ""; + } + } Func InitPanel(Widget panel) { @@ -77,13 +147,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic SettingsUtils.BindCheckboxPref(panel, "HIDE_REPLAY_CHAT_CHECKBOX", gs, "HideReplayChat"); var windowModeDropdown = panel.Get("MODE_DROPDOWN"); - windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(windowModeDropdown, ds, scrollPanel); - windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed ? - "Windowed" : ds.Mode == WindowMode.Fullscreen ? "Fullscreen (Legacy)" : "Fullscreen"; + windowModeDropdown.OnMouseDown = _ => ShowWindowModeDropdown(modData, windowModeDropdown, ds, scrollPanel); + windowModeDropdown.GetText = () => ds.Mode == WindowMode.Windowed + ? modData.Translation.GetString(Windowed) + : ds.Mode == WindowMode.Fullscreen ? legacyFullscreen : fullscreen; var displaySelectionDropDown = panel.Get("DISPLAY_SELECTION_DROPDOWN"); displaySelectionDropDown.OnMouseDown = _ => ShowDisplaySelectionDropdown(displaySelectionDropDown, ds); - var displaySelectionLabel = new CachedTransform(i => $"Display {i + 1}"); + var displaySelectionLabel = new CachedTransform(i => modData.Translation.GetString(Display, Translation.Arguments("number", i + 1))); displaySelectionDropDown.GetText = () => displaySelectionLabel.Update(ds.VideoDisplay); displaySelectionDropDown.IsDisabled = () => Game.Renderer.DisplayCount < 2; @@ -95,18 +166,24 @@ namespace OpenRA.Mods.Common.Widgets.Logic glProfileDropdown.IsDisabled = () => disableProfile; var statusBarsDropDown = panel.Get("STATUS_BAR_DROPDOWN"); - statusBarsDropDown.OnMouseDown = _ => ShowStatusBarsDropdown(statusBarsDropDown, gs); - statusBarsDropDown.GetText = () => gs.StatusBars == StatusBarsType.Standard ? - "Standard" : gs.StatusBars == StatusBarsType.DamageShow ? "Show On Damage" : "Always Show"; + statusBarsDropDown.OnMouseDown = _ => ShowStatusBarsDropdown(modData, statusBarsDropDown, gs); + statusBarsDropDown.GetText = () => gs.StatusBars == StatusBarsType.Standard + ? modData.Translation.GetString(Standard) + : gs.StatusBars == StatusBarsType.DamageShow + ? showOnDamage + : alwaysShow; var targetLinesDropDown = panel.Get("TARGET_LINES_DROPDOWN"); - targetLinesDropDown.OnMouseDown = _ => ShowTargetLinesDropdown(targetLinesDropDown, gs); - targetLinesDropDown.GetText = () => gs.TargetLines == TargetLinesType.Automatic ? - "Automatic" : gs.TargetLines == TargetLinesType.Manual ? "Manual" : "Disabled"; + targetLinesDropDown.OnMouseDown = _ => ShowTargetLinesDropdown(modData, targetLinesDropDown, gs); + targetLinesDropDown.GetText = () => gs.TargetLines == TargetLinesType.Automatic + ? automatic + : gs.TargetLines == TargetLinesType.Manual + ? manual + : disabled; var battlefieldCameraDropDown = panel.Get("BATTLEFIELD_CAMERA_DROPDOWN"); - var battlefieldCameraLabel = new CachedTransform(vs => ViewportSizeNames[vs]); - battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(battlefieldCameraDropDown, viewportSizes, ds); + var battlefieldCameraLabel = new CachedTransform(vs => GetViewportSizeName(modData, vs)); + battlefieldCameraDropDown.OnMouseDown = _ => ShowBattlefieldCameraDropdown(modData, battlefieldCameraDropDown, viewportSizes, ds); battlefieldCameraDropDown.GetText = () => battlefieldCameraLabel.Update(ds.ViewportDistance); BindTextNotificationPoolFilterSettings(panel, gs); @@ -251,13 +328,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; } - static void ShowWindowModeDropdown(DropDownButtonWidget dropdown, GraphicSettings s, ScrollPanelWidget scrollPanel) + static void ShowWindowModeDropdown(ModData modData, DropDownButtonWidget dropdown, GraphicSettings s, ScrollPanelWidget scrollPanel) { var options = new Dictionary() { - { "Fullscreen", WindowMode.PseudoFullscreen }, - { "Fullscreen (Legacy)", WindowMode.Fullscreen }, - { "Windowed", WindowMode.Windowed }, + { modData.Translation.GetString(Fullscreen), WindowMode.PseudoFullscreen }, + { modData.Translation.GetString(LegacyFullscreen), WindowMode.Fullscreen }, + { modData.Translation.GetString(Windowed), WindowMode.Windowed }, }; Func setupItem = (o, itemTemplate) => @@ -300,13 +377,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic } } - static void ShowStatusBarsDropdown(DropDownButtonWidget dropdown, GameSettings s) + static void ShowStatusBarsDropdown(ModData modData, DropDownButtonWidget dropdown, GameSettings s) { var options = new Dictionary() { - { "Standard", StatusBarsType.Standard }, - { "Show On Damage", StatusBarsType.DamageShow }, - { "Always Show", StatusBarsType.AlwaysShow }, + { modData.Translation.GetString(Standard), StatusBarsType.Standard }, + { modData.Translation.GetString(ShowOnDamage), StatusBarsType.DamageShow }, + { modData.Translation.GetString(AlwaysShow), StatusBarsType.AlwaysShow }, }; Func setupItem = (o, itemTemplate) => @@ -355,13 +432,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, profiles, setupItem); } - static void ShowTargetLinesDropdown(DropDownButtonWidget dropdown, GameSettings s) + static void ShowTargetLinesDropdown(ModData modData, DropDownButtonWidget dropdown, GameSettings s) { var options = new Dictionary() { - { "Automatic", TargetLinesType.Automatic }, - { "Manual", TargetLinesType.Manual }, - { "Disabled", TargetLinesType.Disabled }, + { modData.Translation.GetString(Automatic), TargetLinesType.Automatic }, + { modData.Translation.GetString(Manual), TargetLinesType.Manual }, + { modData.Translation.GetString(Disabled), TargetLinesType.Disabled }, }; Func setupItem = (o, itemTemplate) => @@ -377,7 +454,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); } - public static void ShowBattlefieldCameraDropdown(DropDownButtonWidget dropdown, WorldViewportSizes viewportSizes, GraphicSettings gs) + public static void ShowBattlefieldCameraDropdown(ModData modData, DropDownButtonWidget dropdown, WorldViewportSizes viewportSizes, GraphicSettings gs) { Func setupItem = (o, itemTemplate) => { @@ -385,7 +462,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic () => gs.ViewportDistance == o, () => gs.ViewportDistance = o); - var label = ViewportSizeNames[o]; + var label = GetViewportSizeName(modData, o); item.Get("LABEL").GetText = () => label; return item; }; diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs index 14a225fc88..2eb90bc6cc 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/InputSettingsLogic.cs @@ -17,11 +17,53 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class InputSettingsLogic : ChromeLogic { + [TranslationReference] + static readonly string Classic = "classic"; + readonly string classic; + + [TranslationReference] + static readonly string Modern = "modern"; + readonly string modern; + + [TranslationReference] + static readonly string Disabled = "disabled"; + + [TranslationReference] + static readonly string Standard = "standard"; + + [TranslationReference] + static readonly string Inverted = "inverted"; + + [TranslationReference] + static readonly string Joystick = "joystick"; + + [TranslationReference] + static readonly string Alt = "alt"; + + [TranslationReference] + static readonly string Ctrl = "ctrl"; + + [TranslationReference] + static readonly string Meta = "meta"; + + [TranslationReference] + static readonly string Shift = "shift"; + + [TranslationReference] + static readonly string None = "none"; + static InputSettingsLogic() { } + readonly ModData modData; + [ObjectCreator.UseCtor] - public InputSettingsLogic(Action>, Func> registerPanel, string panelID, string label) + public InputSettingsLogic(Action>, Func> registerPanel, string panelID, string label, ModData modData) { + this.modData = modData; + + classic = modData.Translation.GetString(Classic); + modern = modData.Translation.GetString(Modern); + registerPanel(panelID, label, InitPanel, ResetPanel); } @@ -38,11 +80,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic SettingsUtils.BindSliderPref(panel, "UI_SCROLLSPEED_SLIDER", gs, "UIScrollSpeed"); var mouseControlDropdown = panel.Get("MOUSE_CONTROL_DROPDOWN"); - mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(mouseControlDropdown, gs); - mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? "Classic" : "Modern"; + mouseControlDropdown.OnMouseDown = _ => ShowMouseControlDropdown(modData, mouseControlDropdown, gs); + mouseControlDropdown.GetText = () => gs.UseClassicMouseStyle ? classic : modern; var mouseScrollDropdown = panel.Get("MOUSE_SCROLL_TYPE_DROPDOWN"); - mouseScrollDropdown.OnMouseDown = _ => ShowMouseScrollDropdown(mouseScrollDropdown, gs); + mouseScrollDropdown.OnMouseDown = _ => ShowMouseScrollDropdown(modData, mouseScrollDropdown, gs); mouseScrollDropdown.GetText = () => gs.MouseScroll.ToString(); var mouseControlDescClassic = panel.Get("MOUSE_CONTROL_DESC_CLASSIC"); @@ -87,7 +129,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; var zoomModifierDropdown = panel.Get("ZOOM_MODIFIER"); - zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(zoomModifierDropdown, gs); + zoomModifierDropdown.OnMouseDown = _ => ShowZoomModifierDropdown(modData, zoomModifierDropdown, gs); zoomModifierDropdown.GetText = () => gs.ZoomModifier.ToString(); SettingsUtils.AdjustSettingsScrollPanelLayout(scrollPanel); @@ -119,12 +161,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic }; } - public static void ShowMouseControlDropdown(DropDownButtonWidget dropdown, GameSettings s) + public static void ShowMouseControlDropdown(ModData modData, DropDownButtonWidget dropdown, GameSettings s) { var options = new Dictionary() { - { "Classic", true }, - { "Modern", false }, + { modData.Translation.GetString(Classic), true }, + { modData.Translation.GetString(Modern), false }, }; Func setupItem = (o, itemTemplate) => @@ -139,14 +181,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); } - static void ShowMouseScrollDropdown(DropDownButtonWidget dropdown, GameSettings s) + static void ShowMouseScrollDropdown(ModData modData, DropDownButtonWidget dropdown, GameSettings s) { var options = new Dictionary() { - { "Disabled", MouseScrollType.Disabled }, - { "Standard", MouseScrollType.Standard }, - { "Inverted", MouseScrollType.Inverted }, - { "Joystick", MouseScrollType.Joystick }, + { modData.Translation.GetString(Disabled), MouseScrollType.Disabled }, + { modData.Translation.GetString(Standard), MouseScrollType.Standard }, + { modData.Translation.GetString(Inverted), MouseScrollType.Inverted }, + { modData.Translation.GetString(Joystick), MouseScrollType.Joystick }, }; Func setupItem = (o, itemTemplate) => @@ -161,15 +203,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic dropdown.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", 500, options.Keys, setupItem); } - static void ShowZoomModifierDropdown(DropDownButtonWidget dropdown, GameSettings s) + static void ShowZoomModifierDropdown(ModData modData, DropDownButtonWidget dropdown, GameSettings s) { var options = new Dictionary() { - { "Alt", Modifiers.Alt }, - { "Ctrl", Modifiers.Ctrl }, - { "Meta", Modifiers.Meta }, - { "Shift", Modifiers.Shift }, - { "None", Modifiers.None } + { modData.Translation.GetString(Alt), Modifiers.Alt }, + { modData.Translation.GetString(Ctrl), Modifiers.Ctrl }, + { modData.Translation.GetString(Meta), Modifiers.Meta }, + { modData.Translation.GetString(Shift), Modifiers.Shift }, + { modData.Translation.GetString(None), Modifiers.None } }; Func setupItem = (o, itemTemplate) => diff --git a/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs index c923f007e9..7f6ac65c4e 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/Settings/SettingsLogic.cs @@ -19,6 +19,39 @@ namespace OpenRA.Mods.Common.Widgets.Logic { public class SettingsLogic : ChromeLogic { + [TranslationReference] + static readonly string SettingsSaveTitle = "settings-save-title"; + + [TranslationReference] + static readonly string SettingsSavePrompt = "settings-save-prompt"; + + [TranslationReference] + static readonly string SettingsSaveCancel = "settings-save-cancel"; + + [TranslationReference] + static readonly string RestartTitle = "restart-title"; + + [TranslationReference] + static readonly string RestartPrompt = "restart-prompt"; + + [TranslationReference] + static readonly string RestartAccept = "restart-accept"; + + [TranslationReference] + static readonly string RestartCancel = "restart-cancel"; + + [TranslationReference("panel")] + static readonly string ResetTitle = "reset-title"; + + [TranslationReference] + static readonly string ResetPrompt = "reset-prompt"; + + [TranslationReference] + static readonly string ResetAccept = "reset-accept"; + + [TranslationReference] + static readonly string ResetCancel = "reset-cancel"; + readonly Dictionary> leavePanelActions = new Dictionary>(); readonly Dictionary resetPanelActions = new Dictionary(); @@ -34,7 +67,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic static SettingsLogic() { } [ObjectCreator.UseCtor] - public SettingsLogic(Widget widget, Action onExit, WorldRenderer worldRenderer, Dictionary logicArgs) + public SettingsLogic(Widget widget, Action onExit, WorldRenderer worldRenderer, Dictionary logicArgs, ModData modData) { panelContainer = widget.Get("PANEL_CONTAINER"); var panelTemplate = panelContainer.Get("PANEL_TEMPLATE"); @@ -75,11 +108,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic Action closeAndExit = () => { Ui.CloseWindow(); onExit(); }; if (needsRestart) { - Action noRestart = () => ConfirmationDialogs.ButtonPrompt( - title: "Restart Required", - text: "Some changes will not be applied until\nthe game is restarted.", + Action noRestart = () => ConfirmationDialogs.ButtonPrompt(modData, + title: SettingsSaveTitle, + text: SettingsSavePrompt, onCancel: closeAndExit, - cancelText: "Continue"); + cancelText: SettingsSaveCancel); if (!Game.ExternalMods.TryGetValue(ExternalMod.MakeKey(Game.ModData.Manifest), out var external)) { @@ -87,13 +120,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic return; } - ConfirmationDialogs.ButtonPrompt( - title: "Restart Now?", - text: "Some changes will not be applied until\nthe game is restarted. Restart now?", + ConfirmationDialogs.ButtonPrompt(modData, + title: RestartTitle, + text: RestartPrompt, onConfirm: () => Game.SwitchToExternalMod(external, null, noRestart), onCancel: closeAndExit, - confirmText: "Restart Now", - cancelText: "Restart Later"); + confirmText: RestartAccept, + cancelText: RestartCancel); } else closeAndExit(); @@ -107,13 +140,14 @@ namespace OpenRA.Mods.Common.Widgets.Logic Game.Settings.Save(); }; - ConfirmationDialogs.ButtonPrompt( - title: $"Reset \"{panels[activePanel]}\"", - text: "Are you sure you want to reset\nall settings in this panel?", + ConfirmationDialogs.ButtonPrompt(modData, + title: ResetTitle, + titleArguments: Translation.Arguments("panel", panels[activePanel]), + text: ResetPrompt, onConfirm: reset, onCancel: () => { }, - confirmText: "Reset", - cancelText: "Cancel"); + confirmText: ResetAccept, + cancelText: ResetCancel); }; } diff --git a/mods/common/languages/en.ftl b/mods/common/languages/en.ftl index 408a6b3d75..0645f33ff5 100644 --- a/mods/common/languages/en.ftl +++ b/mods/common/languages/en.ftl @@ -17,11 +17,8 @@ invalid-bot-slot = Can't add bots to a slot with another client. invalid-bot-type = Invalid bot type. only-host-change-map = Only the host can change the map. lobby-disconnected = { $player } has left. -player-disconnected = - { $team -> - [0] { $player } has disconnected. - *[other] { $player } (Team { $team }) has disconnected. - } +player-disconnected = { $player } has disconnected. +player-team-disconnected = { $player } (Team { $team }) has disconnected. observer-disconnected = { $player } (Spectator) has disconnected. unknown-map = Map was not found on server. searching-map = Searching for map on the Resource Center... @@ -83,11 +80,8 @@ slot-closed = Your slot was closed by the host. ## Server game-started = Game started -## Server also LobbyUtils -bots-disabled = Bots Disabled - ## PlayerMessageTracker -chat-disabled = +chat-temp-disabled = { $remaining -> [one] Chat is disabled. Please try again in { $remaining } second. *[other] Chat is disabled. Please try again in { $remaining } seconds. @@ -105,6 +99,23 @@ type = Type search-results = Search Results multiple = Multiple +## SaveMapLogic +unpacked = unpacked + +save-map-failed-title = Failed to save map +save-map-failed-prompt = See debug.log for details. +save-map-failed-accept = OK + +overwrite-map-failed-title = Warning +overwrite-map-failed-prompt = By saving you will overwrite + an already existing map. +overwrite-map-failed-confirm = Save + +overwrite-map-outside-edit-title = Warning +overwrite-map-outside-edit-prompt = "The map has been edited from outside the editor. + By saving you may overwrite progress +overwrite-map-outside-edit-confirm = Save + ## GameInfoLogic objectives = Objectives briefing = Briefing @@ -112,7 +123,7 @@ options = Options debug = Debug chat = Chat -## GameInfoObjectivesLogic also GameInfoStatsLogic +## GameInfoObjectivesLogic, GameInfoStatsLogic in-progress = In progress accomplished = Accomplished failed = Failed @@ -121,6 +132,13 @@ failed = Failed mute = Mute this player unmute = Unmute this player +## GameInfoStatsLogic +gone = Gone + +kick-title = Kick { $player }? +kick-prompt = They will not be able to rejoin this game. +kick-accept = Kick + ## GameTimerLogic paused = Paused max-speed = Max Speed @@ -128,13 +146,60 @@ speed = { $percentage }% Speed complete = { $percentage }% complete ## LobbyLogic, InGameChatLogic +chat-disabled = Chat Disabled chat-availability = { $seconds -> - [zero] Chat Disabled [one] Chat available in { $seconds } second... *[other] Chat available in { $seconds } seconds... } +## IngameMenuLogic +leave = Leave +abort-mission = Abort Mission + +leave-mission-title = Leave Mission +leave-mission-prompt = Leave this game and return to the menu? +leave-mission-accept = Leave +leave-mission-cancel = Stay + +restart-button = Restart + +restart-mission-title = Restart +restart-mission-prompt = Are you sure you want to restart? +restart-mission-accept = Restart +restart-mission-cancel = Stay + +surrender-button = Surrender + +surrender-title = Surrender +surrender-prompt = Are you sure you want to surrender? +surrender-accept = Surrender +surrender-cancel = Stay + +load-game-button = Load Game +save-game-button = Save Game + +music-button = Music + +settings-button = Settings + +return-to-map = Return to map +resume = Resume + +save-map-button = Save Map + +error-max-player-title = Error: Max player count exceeded +error-max-player-prompt = There are too many players defined ({ $players }/{ $max }). +error-max-player-accept = Back + +exit-map-button = Exit Map Editor + +exit-map-editor-title = Exit Map Editor +exit-map-editor-prompt-unsaved = Exit and lose all unsaved changes? +exit-map-editor-prompt-deleted = The map may have been deleted outside the editor. +exit-map-editor-confirm-anyway = Exit anyway +exit-map-editor-confirm = Exit + ## IngamePowerBarLogic ## IngamePowerCounterLogic power-usage = Power Usage @@ -162,13 +227,69 @@ army-graph = Army (graph) ## WorldTooltipLogic unrevealed-terrain = Unrevealed Terrain -## ServerlistLogic, GameInfoStatsLogic, ObserverShroudSelectorLogic, SpawnSelectorTooltipLogic -team-no-team = - { $team -> - [zero] No Team - *[other] Team { $team } +## DownloadPackageLogic +downloading = Downloading { $title } +fetching-mirror-list = Fetching list of mirrors... +downloading-from = Downloading from { $host } { $received } { $suffix } +downloading-from-progress = Downloading from { $host } { $received } / { $total } { $suffix } ({ $progress }%) +unknown-host = unknown host +verifying-archive = Verifying archive... +archive-validation-failed = Archive validation failed +extracting = Extracting... +extracting-entry = Extracting { $entry } +archive-extraction-failed = Archive extraction failed +mirror-selection-failed = Online mirror is not available. Please install from an original disc. + +## InstallFromDiscLogic +detecting-drives = Detecting drives +checking-discs = Checking Discs +searching-disc-for = Searching for { $title } +content-package-installation = The following content packages will be installed: +game-discs = Game Discs +digital-installs = Digital Installs +game-content-not-found = Game Content Not Found +alternative-content-sources = Please insert or install one of the following content sources: +installing-content = Installing Content +copying-filename = Copying { $filename } +copying-filename-progress = Copying { $filename } ({ $progress }%) +installation-failed = Installation Failed +check-install-log = Refer to install.log in the logs directory for details. +extracting-filename = Extracting { $filename } +extracting-filename-progress = Extracting { $filename } ({ $progress }%) +cancel = Cancel +retry = Retry + +## InstallFromDiscLogic, LobbyLogic +back = Back + +# InstallFromDiscLogic, ModContentPromptLogic +continue = Continue + +## ModContentLogic +manual-install = Manual Install + +## ModContentPromptLogic +quit = Quit + +## KickClientLogic +kick-client = Kick { $player }? + +## KickSpectatorsLogic +kick-spectators = + { $count -> + [one] Are you sure you want to kick one spectator? + *[other] Are you sure you want to kick { $count } spectators? } +## LobbyLogic +add = Add +remove = Remove +configure-bots = Configure Bots +n-teams = { $count } Teams +humans-vs-bots = Humans vs Bots +free-for-all = Free for all +configure-teams = Configure Teams + ## LobbyLogic, CommonSelectorLogic, InGameChatLogic all = All @@ -178,5 +299,287 @@ none = None ## LobbyLogic, IngameChatLogic team = Team -## ServerListLogic, ReplayBrowserLogic also ObserverShroudSelectorLogic +## LobbyOptionsLogic +not-available = Not Available + +## LobbyUtils +slot = Slot +open = Open +closed = Closed +bots = Bots + +# LobbyUtils, Server +bots-disabled = Bots Disabled + +## MapPreviewLogic +connecting = Connecting... +downloading-map = Downloading { $size } kB +downloading-map-progress = Downloading { $size } kB ({ $progress }%) +retry-install = Retry Install +retry-search = Retry Search +## also MapChooserLogic +created-by = Created by { $author } + +## SpawnSelectorTooltipLogic +disabled-spawn = Disabled spawn +available-spawn = Available spawn + +## DisplaySettingsLogic +close = Close +medium = Medium +far = Far +furthest = Furthest + +windowed = Windowed +legacy-fullscreen = Fullscreen (Legacy) +fullscreen = Fullscreen + +display = Display { $number } + +show-on-damage = Show On Damage +always-show = Always Show + +automatic = Automatic +manual = Manual + +## DisplaySettingsLogic, InputSettingsLogic +disabled = Disabled + +## DisplaySettingsLogic, InputSettingsLogic, IntroductionPromptLogic +classic = Classic +modern = Modern +standard = Standard + +## DisplaySettingsLogic, IntroductionPromptLogic +inverted = Inverted +joystick = Joystick + +alt = Alt +ctrl = Ctrl +meta = Meta +shift = Shift + +## SettingsLogic +settings-save-title = Restart Required +settings-save-prompt = Some changes will not be applied until + the game is restarted. +settings-save-cancel = Continue + +restart-title = Restart Now? +restart-prompt = Some changes will not be applied until + the game is restarted. Restart now? +restart-accept = Restart Now +restart-cancel = Restart Later + +reset-title = Reset { $panel } +reset-prompt = Are you sure you want to reset + all settings in this panel? +reset-accept = Reset +reset-cancel = Cancel + +## AssetBrowserLogic +all-packages = All Packages +length-in-seconds = { $length } sec + +## ConnectionLogic +connecting-to-endpoint = Connecting to { $endpoint }... +could-not-connect-to-target = Could not connect to { $target } +unknown-error = Unknown error +password-required = Password Required +connection-failed = Connection Failed +mod-switch-failed = Failed to switch mod. + +## GameSaveBrowserLogic +rename-save-title = Rename Save +rename-save-prompt = Enter a new file name: +rename-save-accept = Rename + +delete-save-title = Delete selected game save? +delete-save-prompt = Delete '{ $save }' +delete-save-accept = Delete + +delete-all-saves-title = Delete all game saves? +delete-all-saves-prompt = + { $count -> + [one] Delete { $count } save. + *[other] Delete { $count } saves. + } +delete-all-saves-accept = Delete All + +save-deletion-failed = Failed to delete save file '{ $savePath }'. See the logs for details. + +overwrite-save-title = Overwrite saved game? +overwrite-save-prompt = Overwrite { $file }? +overwrite-save-accept = Overwrite + +## MainMenuLogic +loading-news = Loading news +news-retrival-failed = Failed to retrieve news: { $message } +news-parsing-failed = Failed to parse news: { $message } + +## MapChooserLogic +all-maps = All Maps +no-matches = No matches +player-players = + { $players -> + [one] { $players } Player + *[other] { $players } Players + } +map-size-huge = (Huge) +map-size-large = (Large) +map-size-medium = (Medium) +map-size-small = (Small) + +map-deletion-failed = Failed to delete map '{ $map }'. See the debug.log file for details. + +delete-map-title = Delete map +delete-map-prompt = Delete the map '{ $title }'? +delete-map-accept = Delete + +delete-all-maps-title = Delete maps +delete-all-maps-prompt = Delete all maps on this page? +delete-all-maps-accept = Delete + +## MissionBrowserLogic +no-video-title = Video not installed +no-video-text = The game videos can be installed from the + "Manage Content" menu in the mod chooser. +no-video-cancel = Back + +cant-play-title = Unable to play video +cant-play-prompt = Something went wrong during video playback. +cant-play-cancel = Back + +## MusicPlayerLogic +sound-muted = Audio has been muted in settings. +no-song-playing = No song playing + +## MuteHotkeyLogic +audio-muted = Audio muted. +audio-unmuted = Audio unmuted. + +## PlayerProfileLogic +loading-player-profile = Loading player profile... +loading-player-profile-failed = Failed to load player profile. + +## ReplayBrowserLogic +duration = Duration: { $time } +singleplayer = Singleplayer +multiplayer = Multiplayer + +today = Today +last-week = Last 7 days +last-fortnight = Last 14 days +last-month = Last 30 days + +replay-duration-very-short = Under 5 min +replay-duration-short = Short (10 min) +replay-duration-medium = Medium (30 min) +replay-duration-long = Long (60+ min) + +rename-replay-title = Rename Replay +rename-replay-prompt = Enter a new file name: +rename-replay-accept = Rename + +delete-replay-title = Delete selected replay? +delete-replay-prompt = Delete replay { $replay }? +delete-replay-accept = Delete + +delete-all-replays-title = Delete all selected replays? +delete-all-replays-prompt = + { $count -> + [one] Delete { $count } replay. + *[other] Delete { $count } replays. + } +delete-all-replays-accept = Delete All + +replay-deletion-failed = Failed to delete replay file '{ $file }'. See the debug.log file for details. + +## ReplayUtils +incompatible-replay-title = Incompatible Replay +incompatible-replay-prompt = Replay metadata could not be read. +-incompatible-replay-recorded = It was recorded with +incompatible-replay-unknown-version = { -incompatible-replay-recorded } an unknown version: { $version }. +incompatible-replay-unknown-mod = { -incompatible-replay-recorded } an unknown mod: { $mod }. +incompatible-replay-unavailable-mod = { -incompatible-replay-recorded } an unavailable mod: { $mod }. +incompatible-replay-incompatible-version = { -incompatible-replay-recorded } an incompatible version: { $version }. +incompatible-replay-unavailable-map = { -incompatible-replay-recorded } an unavailable map: { $map }. + +## ServerCreationLogic +internet-server-nat-A = Internet Server (UPnP/NAT-PMP +internet-server-nat-B-enabled = Enabled +internet-server-nat-B-not-supported = Not Supported +internet-server-nat-B-disabled = Disabled +internet-server-nat-C = ): + +local-server = Local Server: + +server-creation-failed-prompt = Could not listen on port { $port } +server-creation-failed-port-used = Check if the port is already being used. +server-creation-failed-error = Error is: "{ $message }" ({ $code }) +server-creation-failed-title = Server Creation Failed +server-creation-failed-cancel = Back + +## ServerListLogic +players-online = + { $players -> + [one] { $players } Player Online + *[other] { $players } Players Online + } + +search-status-failed = Failed to query server list. +search-status-no-games = No games found. Try changing filters. +no-server-selected = No Server Selected + +map-status-searching = Searching... +map-classification-unknown = Unknown Map + +players-label = + { $players -> + [0] No Players + [one] One Player + *[other] { $players } Players + } + +bots-label = + { $bots -> + [0] No Bots + [one] One Bot + *[other] { $bots } Bots + } + +## ServerListLogic, ReplayBrowserLogic, ObserverShroudSelectorLogic players = Players + +## ServerListLogic, GameInfoStatsLogic +spectators = Spectators +spectators-label = + { $spectators -> + [0] No Spectators + [one] One Spectator + *[other] { $spectators } Spectators + } + +## ServerlistLogic, GameInfoStatsLogic, ObserverShroudSelectorLogic, SpawnSelectorTooltipLogic, ReplayBrowserLogic +team-number = Team { $team } +no-team = No Team + +playing = Playing +waiting = Waiting + +n-other-players = + { $players -> + [one] One other player + *[other] { $players } other players + } + +in-progress-for = + { $minutes -> + [0] In progress + [one] In progress for { $minutes } minute. + *[other] In progress for { $minutes } minutes. + } +password-protected = Password protected +waiting-for-players = Waiting for players +server-shutting-down = Server shutting down +unknown-server-state = Unknown server state diff --git a/mods/modcontent/mod.yaml b/mods/modcontent/mod.yaml index c01ad6daa7..0d90cf9a0b 100644 --- a/mods/modcontent/mod.yaml +++ b/mods/modcontent/mod.yaml @@ -35,6 +35,9 @@ ChromeMetrics: common|metrics.yaml modcontent|metrics.yaml +Translations: + common|languages/en.ftl + Fonts: Tiny: Font: common|FreeSans.ttf