diff --git a/.github/workflows/upload-crowdin.yml b/.github/workflows/upload-crowdin.yml new file mode 100644 index 0000000..e885852 --- /dev/null +++ b/.github/workflows/upload-crowdin.yml @@ -0,0 +1,22 @@ +name: Upload to Crowdin +on: + push: + branches: + - master + paths: + - 'Pal.Client/Properties/*.resx' +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Crowdin Action + uses: crowdin/github-action@1.4.9 + with: + upload_sources: true + upload_translations: true + download_translations: false + crowdin_branch_name: ${{ github.ref_name }} + env: + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/Pal.Client/Configuration.cs b/Pal.Client/Configuration.cs index f8e5fbf..af3133a 100644 --- a/Pal.Client/Configuration.cs +++ b/Pal.Client/Configuration.cs @@ -10,12 +10,13 @@ using System.IO; using System.Linq; using System.Numerics; using System.Security.Cryptography; +using Pal.Client.Extensions; namespace Pal.Client { public class Configuration : IPluginConfiguration { - private static readonly byte[] _entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 }; + private static readonly byte[] Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 }; public int Version { get; set; } = 6; @@ -121,7 +122,7 @@ namespace Pal.Client { new TickScheduler(delegate { - Service.Chat.PrintError("[Palace Pal] Due to a bug, some coffers were accidentally saved as traps. To fix the related display issue, locally cached data was cleaned up."); + Service.Chat.PalError("Due to a bug, some coffers were accidentally saved as traps. To fix the related display issue, locally cached data was cleaned up."); Service.Chat.PrintError($"If you have any backup tools installed, please restore the contents of '{Service.PluginInterface.GetPluginConfigDirectory()}' to any backup from February 2, 2023 or before."); Service.Chat.PrintError("You can also manually restore .json.bak files (by removing the '.bak') if you have not been in any deep dungeon since February 2, 2023."); }, 2500); @@ -182,7 +183,7 @@ namespace Pal.Client /// This has no impact on what roles the JWT actually contains, but is just to make it /// easier to draw a consistent UI. The server will still reject unauthorized calls. /// - public List CachedRoles { get; set; } = new List(); + public List CachedRoles { get; set; } = new(); } public class AccountIdConverter : JsonConverter @@ -204,7 +205,7 @@ namespace Pal.Client { try { - byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(text.Substring(2)), _entropy, DataProtectionScope.CurrentUser); + byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(text.Substring(2)), Entropy, DataProtectionScope.CurrentUser); return new Guid(guidBytes); } catch (CryptographicException e) @@ -229,7 +230,7 @@ namespace Pal.Client string text; try { - byte[] guidBytes = ProtectedData.Protect(g.ToByteArray(), _entropy, DataProtectionScope.CurrentUser); + byte[] guidBytes = ProtectedData.Protect(g.ToByteArray(), Entropy, DataProtectionScope.CurrentUser); text = $"s:{Convert.ToBase64String(guidBytes)}"; } catch (CryptographicException) diff --git a/Pal.Client/DownloadGithubActions.sh b/Pal.Client/DownloadGithubActions.sh deleted file mode 100644 index 5aa23ce..0000000 --- a/Pal.Client/DownloadGithubActions.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -curl -O https://raw.githubusercontent.com/karashiiro/DalamudPluginProjectTemplate/master/.github/workflows/dotnet.yml -mkdir .github -mkdir .github/workflows -mv dotnet.yml .github/workflows \ No newline at end of file diff --git a/Pal.Client/Extensions/ChatExtensions.cs b/Pal.Client/Extensions/ChatExtensions.cs new file mode 100644 index 0000000..6d7eeda --- /dev/null +++ b/Pal.Client/Extensions/ChatExtensions.cs @@ -0,0 +1,10 @@ +using Dalamud.Game.Gui; +using Pal.Client.Properties; + +namespace Pal.Client.Extensions; + +public static class ChatExtensions +{ + public static void PalError(this ChatGui chat, string e) + => chat.PrintError($"[{Localization.Palace_Pal}] {e}"); +} diff --git a/Pal.Client/WindowSystemExtensions.cs b/Pal.Client/Extensions/WindowSystemExtensions.cs similarity index 52% rename from Pal.Client/WindowSystemExtensions.cs rename to Pal.Client/Extensions/WindowSystemExtensions.cs index 504d3ab..15809c2 100644 --- a/Pal.Client/WindowSystemExtensions.cs +++ b/Pal.Client/Extensions/WindowSystemExtensions.cs @@ -1,14 +1,14 @@ -using Dalamud.Interface.Windowing; -using System.Linq; +using System.Linq; +using Dalamud.Interface.Windowing; -namespace Pal.Client +namespace Pal.Client.Extensions { internal static class WindowSystemExtensions { public static T? GetWindow(this WindowSystem windowSystem) where T : Window { - return windowSystem.Windows.Select(w => w as T).FirstOrDefault(w => w != null); + return windowSystem.Windows.OfType().FirstOrDefault(); } } } diff --git a/Pal.Client/LocalState.cs b/Pal.Client/LocalState.cs index dc88369..4cc8b38 100644 --- a/Pal.Client/LocalState.cs +++ b/Pal.Client/LocalState.cs @@ -13,8 +13,8 @@ namespace Pal.Client /// internal class LocalState { - private static readonly JsonSerializerOptions _jsonSerializerOptions = new JsonSerializerOptions { IncludeFields = true }; - private static readonly int _currentVersion = 4; + private static readonly JsonSerializerOptions JsonSerializerOptions = new() { IncludeFields = true }; + private const int CurrentVersion = 4; public uint TerritoryType { get; set; } public ConcurrentBag Markers { get; set; } = new(); @@ -51,12 +51,12 @@ namespace Pal.Client // v1 only had a list of markers, not a JSON object as root localState = new LocalState(territoryType) { - Markers = new ConcurrentBag(JsonSerializer.Deserialize>(content, _jsonSerializerOptions) ?? new()), + Markers = new ConcurrentBag(JsonSerializer.Deserialize>(content, JsonSerializerOptions) ?? new()), }; } else { - var save = JsonSerializer.Deserialize(content, _jsonSerializerOptions); + var save = JsonSerializer.Deserialize(content, JsonSerializerOptions); if (save == null) return null; @@ -75,7 +75,7 @@ namespace Pal.Client marker.RemoteSeenOn = marker.RemoteSeenOn.Select(x => x.PadRight(14).Substring(0, 13)).ToList(); } - if (version < _currentVersion) + if (version < CurrentVersion) localState.Save(); return localState; @@ -112,9 +112,9 @@ namespace Pal.Client { File.WriteAllText(path, JsonSerializer.Serialize(new SaveFile { - Version = _currentVersion, + Version = CurrentVersion, Markers = new HashSet(Markers) - }, _jsonSerializerOptions)); + }, JsonSerializerOptions)); } } @@ -142,7 +142,7 @@ namespace Pal.Client // When saving a floor state, any markers not seen, not remote seen, and not having an import id are removed; // so it is possible to remove "wrong" markers by not having them be in the current import. foreach (var marker in Markers) - marker.Imports.RemoveAll(id => importIds.Contains(id)); + marker.Imports.RemoveAll(importIds.Contains); } public class SaveFile diff --git a/Pal.Client/Marker.cs b/Pal.Client/Marker.cs index f7afbc6..e20d0fe 100644 --- a/Pal.Client/Marker.cs +++ b/Pal.Client/Marker.cs @@ -17,7 +17,7 @@ namespace Pal.Client /// /// Whether we have encountered the trap/coffer at this location in-game. /// - public bool Seen { get; set; } = false; + public bool Seen { get; set; } /// /// Network id for the server you're currently connected to. @@ -35,20 +35,20 @@ namespace Pal.Client /// Which account ids this marker was seen. This is a list merely to support different remote endpoints /// (where each server would assign you a different id). /// - public List RemoteSeenOn { get; set; } = new List(); + public List RemoteSeenOn { get; set; } = new(); /// /// Whether this marker was requested to be seen, to avoid duplicate requests. /// [JsonIgnore] - public bool RemoteSeenRequested { get; set; } = false; + public bool RemoteSeenRequested { get; set; } /// /// To keep track of which markers were imported through a downloaded file, we save the associated import-id. /// /// Importing another file for the same remote server will remove the old import-id, and add the new import-id here. /// - public List Imports { get; set; } = new List(); + public List Imports { get; set; } = new(); public bool WasImported { get; set; } diff --git a/Pal.Client/Net/RemoteApi.AccountService.cs b/Pal.Client/Net/RemoteApi.AccountService.cs index 3f4a33a..dba9bec 100644 --- a/Pal.Client/Net/RemoteApi.AccountService.cs +++ b/Pal.Client/Net/RemoteApi.AccountService.cs @@ -9,6 +9,8 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Pal.Client.Extensions; +using Pal.Client.Properties; namespace Pal.Client.Net { @@ -19,7 +21,7 @@ namespace Pal.Client.Net if (Service.Configuration.Mode != Configuration.EMode.Online) { PluginLog.Debug("TryConnect: Not Online, not attempting to establish a connection"); - return (false, "You are not online."); + return (false, Localization.ConnectionError_NotOnline); } if (_channel == null || !(_channel.State == ConnectivityState.Ready || _channel.State == ConnectivityState.Idle)) @@ -61,17 +63,17 @@ namespace Pal.Client.Net PluginLog.Error($"TryConnect: Account creation failed with error {createAccountReply.Error}"); if (createAccountReply.Error == CreateAccountError.UpgradeRequired && !_warnedAboutUpgrade) { - Service.Chat.PrintError("[Palace Pal] Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer."); + Service.Chat.PalError(Localization.ConnectionError_OldVersion); _warnedAboutUpgrade = true; } - return (false, $"Could not create account ({createAccountReply.Error})."); + return (false, string.Format(Localization.ConnectionError_CreateAccountFailed, createAccountReply.Error)); } } if (AccountId == null) { PluginLog.Warning("TryConnect: No account id to login with"); - return (false, "No account-id after account was attempted to be created."); + return (false, Localization.ConnectionError_CreateAccountReturnedNoId); } if (!_loginInfo.IsValid) @@ -104,21 +106,21 @@ namespace Pal.Client.Net return await TryConnect(cancellationToken, retry: false); } else - return (false, "Invalid account id."); + return (false, Localization.ConnectionError_InvalidAccountId); } if (loginReply.Error == LoginError.UpgradeRequired && !_warnedAboutUpgrade) { - Service.Chat.PrintError("[Palace Pal] Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer."); + Service.Chat.PalError(Localization.ConnectionError_OldVersion); _warnedAboutUpgrade = true; } - return (false, $"Could not log in ({loginReply.Error})."); + return (false, string.Format(Localization.ConnectionError_LoginFailed, loginReply.Error)); } } if (!_loginInfo.IsValid) { PluginLog.Error($"TryConnect: Login state is loggedIn={_loginInfo.IsLoggedIn}, expired={_loginInfo.IsExpired}"); - return (false, "No login information available."); + return (false, Localization.ConnectionError_LoginReturnedNoToken); } return (true, string.Empty); @@ -136,14 +138,14 @@ namespace Pal.Client.Net var connectionResult = await TryConnect(cancellationToken, loggerFactory: _grpcToPluginLogLoggerFactory); if (!connectionResult.Success) - return $"Could not connect to server: {connectionResult.Error}"; + return string.Format(Localization.ConnectionError_CouldNotConnectToServer, connectionResult.Error); PluginLog.Information("VerifyConnection: Connection established, trying to verify auth token"); var accountClient = new AccountService.AccountServiceClient(_channel); await accountClient.VerifyAsync(new VerifyRequest(), headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken); PluginLog.Information("VerifyConnection: Verification returned no errors."); - return "Connection successful."; + return Localization.ConnectionSuccessful; } internal class LoginInfo diff --git a/Pal.Client/Net/RemoteApi.Utils.cs b/Pal.Client/Net/RemoteApi.Utils.cs index f7a3a2f..fb3c965 100644 --- a/Pal.Client/Net/RemoteApi.Utils.cs +++ b/Pal.Client/Net/RemoteApi.Utils.cs @@ -9,13 +9,13 @@ namespace Pal.Client.Net { private Metadata UnauthorizedHeaders() => new Metadata { - { "User-Agent", UserAgent }, + { "User-Agent", _userAgent }, }; private Metadata AuthorizedHeaders() => new Metadata { { "Authorization", $"Bearer {_loginInfo?.AuthToken}" }, - { "User-Agent", UserAgent }, + { "User-Agent", _userAgent }, }; private SslClientAuthenticationOptions? GetSslClientAuthenticationOptions() diff --git a/Pal.Client/Net/RemoteApi.cs b/Pal.Client/Net/RemoteApi.cs index f19e757..713c771 100644 --- a/Pal.Client/Net/RemoteApi.cs +++ b/Pal.Client/Net/RemoteApi.cs @@ -12,12 +12,12 @@ namespace Pal.Client.Net #else public static string RemoteUrl { get; } = "https://pal.μ.tv"; #endif - private readonly string UserAgent = $"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}"; + private readonly string _userAgent = $"{typeof(RemoteApi).Assembly.GetName().Name?.Replace(" ", "")}/{typeof(RemoteApi).Assembly.GetName().Version?.ToString(2)}"; private readonly ILoggerFactory _grpcToPluginLogLoggerFactory = LoggerFactory.Create(builder => builder.AddProvider(new GrpcLoggerProvider()).AddFilter("Grpc", LogLevel.Trace)); private GrpcChannel? _channel; - private LoginInfo _loginInfo = new LoginInfo(null); + private LoginInfo _loginInfo = new(null); private bool _warnedAboutUpgrade = false; public Configuration.AccountInfo? Account diff --git a/Pal.Client/Pal.Client.csproj b/Pal.Client/Pal.Client.csproj index 934af7f..a9b711a 100644 --- a/Pal.Client/Pal.Client.csproj +++ b/Pal.Client/Pal.Client.csproj @@ -28,6 +28,10 @@ + + ResXFileCodeGenerator + Localization.Designer.cs + @@ -85,6 +89,14 @@ + + + True + True + Localization.resx + + + diff --git a/Pal.Client/Plugin.cs b/Pal.Client/Plugin.cs index fc7a114..44c1a83 100644 --- a/Pal.Client/Plugin.cs +++ b/Pal.Client/Plugin.cs @@ -8,7 +8,6 @@ using Dalamud.Game.Text.SeStringHandling; using Dalamud.Interface.Windowing; using Dalamud.Logging; using Dalamud.Plugin; -using ECommons; using Grpc.Core; using ImGuiNET; using Lumina.Excel.GeneratedSheets; @@ -19,17 +18,20 @@ using Pal.Common; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Pal.Client.Extensions; +using Pal.Client.Properties; namespace Pal.Client { public class Plugin : IDalamudPlugin { - internal const uint COLOR_INVISIBLE = 0; + internal const uint ColorInvisible = 0; private LocalizedChatMessages _localizedChatMessages = new(); @@ -45,10 +47,12 @@ namespace Pal.Client internal ConcurrentQueue NextUpdateObjects { get; } = new(); internal IRenderer Renderer { get; private set; } = null!; - public string Name => "Palace Pal"; + public string Name => Localization.Palace_Pal; public Plugin(DalamudPluginInterface pluginInterface, ChatGui chat) { + LanguageChanged(pluginInterface.UiLanguage); + PluginLog.Information($"Install source: {pluginInterface.SourceRepository}"); #if RELEASE @@ -59,7 +63,7 @@ namespace Pal.Client && !pluginInterface.SourceRepository.StartsWith("https://raw.githubusercontent.com/carvelli/") && !pluginInterface.SourceRepository.StartsWith("https://github.com/carvelli/")) { - chat.PrintError("[Palace Pal] Please install this plugin from the official repository at https://github.com/carvelli/Dalamud-Plugins to continue using it."); + chat.PalError(string.Format(Localization.Error_WrongRepository, "https://github.com/carvelli/Dalamud-Plugins")); throw new InvalidOperationException(); } #endif @@ -94,11 +98,12 @@ namespace Pal.Client pluginInterface.UiBuilder.Draw += Draw; pluginInterface.UiBuilder.OpenConfigUi += OnOpenConfigUi; + pluginInterface.LanguageChanged += LanguageChanged; Service.Framework.Update += OnFrameworkUpdate; Service.Chat.ChatMessage += OnChatMessage; Service.CommandManager.AddHandler("/pal", new CommandInfo(OnCommand) { - HelpMessage = "Open the configuration/debug window" + HelpMessage = Localization.Command_pal_HelpText }); ReloadLanguageStrings(); @@ -120,7 +125,7 @@ namespace Pal.Client { if (Service.Configuration.FirstUse) { - Service.Chat.PrintError("[Palace Pal] Please finish the first-time setup first."); + Service.Chat.PalError(Localization.Error_FirstTimeSetupRequired); return; } @@ -146,7 +151,7 @@ namespace Pal.Client #if DEBUG case "update-saves": LocalState.UpdateAll(); - Service.Chat.Print("Updated all locally cached marker files to latest version."); + Service.Chat.Print(Localization.Command_pal_updatesaves); break; #endif @@ -168,13 +173,13 @@ namespace Pal.Client break; default: - Service.Chat.PrintError($"[Palace Pal] Unknown sub-command '{arguments}' for '{command}'."); + Service.Chat.PalError(string.Format(Localization.Command_pal_UnknownSubcommand, arguments, command)); break; } } catch (Exception e) { - Service.Chat.PrintError($"[Palace Pal] {e}"); + Service.Chat.PalError(e.ToString()); } } @@ -186,6 +191,7 @@ namespace Pal.Client Service.CommandManager.RemoveHandler("/pal"); Service.PluginInterface.UiBuilder.Draw -= Draw; Service.PluginInterface.UiBuilder.OpenConfigUi -= OnOpenConfigUi; + Service.PluginInterface.LanguageChanged -= LanguageChanged; Service.Framework.Update -= OnFrameworkUpdate; Service.Chat.ChatMessage -= OnChatMessage; @@ -243,6 +249,9 @@ namespace Pal.Client return; } + private void LanguageChanged(string langcode) + => Localization.Culture = new CultureInfo(langcode); + private void OnFrameworkUpdate(Framework framework) { if (Service.Configuration.FirstUse) @@ -410,8 +419,8 @@ namespace Pal.Client private void HandleEphemeralMarkers(IList visibleMarkers, bool recreateLayout) { - recreateLayout |= EphemeralMarkers.Any(existingMarker => !visibleMarkers.Any(x => x == existingMarker)); - recreateLayout |= visibleMarkers.Any(visibleMarker => !EphemeralMarkers.Any(x => x == visibleMarker)); + recreateLayout |= EphemeralMarkers.Any(existingMarker => visibleMarkers.All(x => x != existingMarker)); + recreateLayout |= visibleMarkers.Any(visibleMarker => EphemeralMarkers.All(x => x != visibleMarker)); if (recreateLayout) { @@ -440,24 +449,19 @@ namespace Pal.Client private uint DetermineColor(Marker marker, IList visibleMarkers) { - if (marker.Type == Marker.EType.Trap) + switch (marker.Type) { - if (PomanderOfSight == PomanderState.Inactive || !Service.Configuration.OnlyVisibleTrapsAfterPomander || visibleMarkers.Any(x => x == marker)) + case Marker.EType.Trap when PomanderOfSight == PomanderState.Inactive || !Service.Configuration.OnlyVisibleTrapsAfterPomander || visibleMarkers.Any(x => x == marker): return ImGui.ColorConvertFloat4ToU32(Service.Configuration.TrapColor); - else - return COLOR_INVISIBLE; - } - else if (marker.Type == Marker.EType.Hoard) - { - if (PomanderOfIntuition == PomanderState.Inactive || !Service.Configuration.OnlyVisibleHoardAfterPomander || visibleMarkers.Any(x => x == marker)) + case Marker.EType.Hoard when PomanderOfIntuition == PomanderState.Inactive || !Service.Configuration.OnlyVisibleHoardAfterPomander || visibleMarkers.Any(x => x == marker): return ImGui.ColorConvertFloat4ToU32(Service.Configuration.HoardColor); - else - return COLOR_INVISIBLE; + case Marker.EType.SilverCoffer: + return ImGui.ColorConvertFloat4ToU32(Service.Configuration.SilverCofferColor); + case Marker.EType.Trap: + case Marker.EType.Hoard: + default: + return ImGui.ColorConvertFloat4ToU32(new Vector4(1, 0.5f, 1, 0.4f)); } - else if (marker.Type == Marker.EType.SilverCoffer) - return ImGui.ColorConvertFloat4ToU32(Service.Configuration.SilverCofferColor); - else - return ImGui.ColorConvertFloat4ToU32(new Vector4(1, 0.5f, 1, 0.4f)); } private void CreateRenderElement(Marker marker, List elements, uint color, bool fill = false) @@ -532,7 +536,7 @@ namespace Pal.Client { if (!Service.RemoteApi.HasRoleOnCurrentServer("statistics:view")) { - Service.Chat.Print("[Palace Pal] You can view statistics for the floor you're currently on by opening the 'Debug' tab in the configuration window."); + Service.Chat.PalError(Localization.Command_pal_stats_CurrentFloor); return; } @@ -547,16 +551,16 @@ namespace Pal.Client } else { - Service.Chat.PrintError("[Palace Pal] Unable to fetch statistics."); + Service.Chat.PalError(Localization.Command_pal_stats_UnableToFetchStatistics); } } catch (RpcException e) when (e.StatusCode == StatusCode.PermissionDenied) { - Service.Chat.Print("[Palace Pal] You can view statistics for the floor you're currently on by opening the 'Debug' tab in the configuration window."); + Service.Chat.Print(Localization.Command_pal_stats_CurrentFloor); } catch (Exception e) { - Service.Chat.PrintError($"[Palace Pal] {e}"); + Service.Chat.PalError(e.ToString()); } } @@ -573,7 +577,7 @@ namespace Pal.Client var nearbyMarkers = state.Markers .Where(m => predicate(m)) - .Where(m => m.RenderElement != null && m.RenderElement.Color != COLOR_INVISIBLE) + .Where(m => m.RenderElement != null && m.RenderElement.Color != ColorInvisible) .Select(m => new { m = m, distance = (playerPosition - m.Position)?.Length() ?? float.MaxValue }) .OrderBy(m => m.distance) .Take(5) diff --git a/Pal.Client/Properties/Localization.Designer.cs b/Pal.Client/Properties/Localization.Designer.cs new file mode 100644 index 0000000..396182b --- /dev/null +++ b/Pal.Client/Properties/Localization.Designer.cs @@ -0,0 +1,811 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Pal.Client.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Localization { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Localization() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Pal.Client.Properties.Localization", typeof(Localization).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Please chose one of the options above.. + /// + internal static string Agreement_PickOneOption { + get { + return ResourceManager.GetString("Agreement_PickOneOption", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I understand I'm using this plugin on my own risk.. + /// + internal static string Agreement_UsingThisOnMyOwnRisk { + get { + return ResourceManager.GetString("Agreement_UsingThisOnMyOwnRisk", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to View plugin & server source code. + /// + internal static string Agreement_ViewPluginAndServerSourceCode { + get { + return ResourceManager.GetString("Agreement_ViewPluginAndServerSourceCode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to While this is not an automation feature, you're still very likely to break the ToS.. + /// + internal static string Agreement_Warning1 { + get { + return ResourceManager.GetString("Agreement_Warning1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Other players in your party can always see where you're standing/walking.. + /// + internal static string Agreement_Warning2 { + get { + return ResourceManager.GetString("Agreement_Warning2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As such, please avoid mentioning it in-game and do not share videos/screenshots.. + /// + internal static string Agreement_Warning3 { + get { + return ResourceManager.GetString("Agreement_Warning3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open the configuration/debug window. + /// + internal static string Command_pal_HelpText { + get { + return ResourceManager.GetString("Command_pal_HelpText", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can view statistics for the floor you're currently on by opening the 'Debug' tab in the configuration window.. + /// + internal static string Command_pal_stats_CurrentFloor { + get { + return ResourceManager.GetString("Command_pal_stats_CurrentFloor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unable to fetch statistics.. + /// + internal static string Command_pal_stats_UnableToFetchStatistics { + get { + return ResourceManager.GetString("Command_pal_stats_UnableToFetchStatistics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unknown sub-command '{0}' for '{1}'.. + /// + internal static string Command_pal_UnknownSubcommand { + get { + return ResourceManager.GetString("Command_pal_UnknownSubcommand", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updated all locally cached marker files to latest version.. + /// + internal static string Command_pal_updatesaves { + get { + return ResourceManager.GetString("Command_pal_updatesaves", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are NOT in a deep dungeon.. + /// + internal static string Config_Debug_NotInADeepDungeon { + get { + return ResourceManager.GetString("Config_Debug_NotInADeepDungeon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save as:. + /// + internal static string Config_Export_SaveAs { + get { + return ResourceManager.GetString("Config_Export_SaveAs", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Export all markers from {0}:. + /// + internal static string Config_ExportSource { + get { + return ResourceManager.GetString("Config_ExportSource", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hoard Coffer color. + /// + internal static string Config_HoardCoffers_Color { + get { + return ResourceManager.GetString("Config_HoardCoffers_Color", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hide hoard coffers not on current floor. + /// + internal static string Config_HoardCoffers_HideImpossible { + get { + return ResourceManager.GetString("Config_HoardCoffers_HideImpossible", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to When using a Pomander of intuition, only the actual hoard coffer location is visible, all other (potential) hoard coffers are hidden.. + /// + internal static string Config_HoardCoffers_HideImpossible_ToolTip { + get { + return ResourceManager.GetString("Config_HoardCoffers_HideImpossible_ToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show hoard coffers. + /// + internal static string Config_HoardCoffers_Show { + get { + return ResourceManager.GetString("Config_HoardCoffers_Show", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Visit GitHub. + /// + internal static string Config_Import_VisitGitHub { + get { + return ResourceManager.GetString("Config_Import_VisitGitHub", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exports are available from {0} (as *.pal files).. + /// + internal static string Config_ImportDownloadLocation { + get { + return ResourceManager.GetString("Config_ImportDownloadLocation", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Using an export is useful if you're unable to connect to the server, or don't wish to share your findings.. + /// + internal static string Config_ImportExplanation1 { + get { + return ResourceManager.GetString("Config_ImportExplanation1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Exports are (currently) generated manually, and they only include traps and hoard coffers encountered by 5 or more people. This may lead to higher floors having very sporadic coverage, but commonly run floors (e.g. PotD 51-60, HoH 21-30) are closer to complete.. + /// + internal static string Config_ImportExplanation2 { + get { + return ResourceManager.GetString("Config_ImportExplanation2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you aren't offline, importing a file won't have any noticeable effect.. + /// + internal static string Config_ImportExplanation3 { + get { + return ResourceManager.GetString("Config_ImportExplanation3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Never upload discoveries, show only traps and coffers I found myself. + /// + internal static string Config_NeverUploadDiscoveries_ShowMyTraps { + get { + return ResourceManager.GetString("Config_NeverUploadDiscoveries_ShowMyTraps", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Simple. + /// + internal static string Config_Renderer_Simple { + get { + return ResourceManager.GetString("Config_Renderer_Simple", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to experimental. + /// + internal static string Config_Renderer_Simple_Hint { + get { + return ResourceManager.GetString("Config_Renderer_Simple_Hint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Splatoon. + /// + internal static string Config_Renderer_Splatoon { + get { + return ResourceManager.GetString("Config_Renderer_Splatoon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to default, required Splatoon to be installed. + /// + internal static string Config_Renderer_Splatoon_Hint { + get { + return ResourceManager.GetString("Config_Renderer_Splatoon_Hint", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to File to Import:. + /// + internal static string Config_SelectImportFile { + get { + return ResourceManager.GetString("Config_SelectImportFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Select which render backend to use for markers:. + /// + internal static string Config_SelectRenderBackend { + get { + return ResourceManager.GetString("Config_SelectRenderBackend", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Silver Coffer color. + /// + internal static string Config_SilverCoffer_Color { + get { + return ResourceManager.GetString("Config_SilverCoffer_Color", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Draw filled. + /// + internal static string Config_SilverCoffer_Filled { + get { + return ResourceManager.GetString("Config_SilverCoffer_Filled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show silver coffers on current floor. + /// + internal static string Config_SilverCoffer_Show { + get { + return ResourceManager.GetString("Config_SilverCoffer_Show", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Shows all the silver coffers visible to you on the current floor. + ///This is not synchronized with other players and not saved between floors/runs.. + /// + internal static string Config_SilverCoffers_ToolTip { + get { + return ResourceManager.GetString("Config_SilverCoffers_ToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Draw trap & coffer circles around self. + /// + internal static string Config_Splatoon_DrawCircles { + get { + return ResourceManager.GetString("Config_Splatoon_DrawCircles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Splatoon Test:. + /// + internal static string Config_Splatoon_Test { + get { + return ResourceManager.GetString("Config_Splatoon_Test", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start Export. + /// + internal static string Config_StartExport { + get { + return ResourceManager.GetString("Config_StartExport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Start Import. + /// + internal static string Config_StartImport { + get { + return ResourceManager.GetString("Config_StartImport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Test Connection. + /// + internal static string Config_TestConnection { + get { + return ResourceManager.GetString("Config_TestConnection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trap color. + /// + internal static string Config_Traps_Color { + get { + return ResourceManager.GetString("Config_Traps_Color", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hide traps not on current floor. + /// + internal static string Config_Traps_HideImpossible { + get { + return ResourceManager.GetString("Config_Traps_HideImpossible", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to When using a Pomander of Sight, only the actual trap locations are visible, all other traps are hidden. + ///When using a Pomander of Safety, all traps are hidden.. + /// + internal static string Config_Traps_HideImpossible_ToolTip { + get { + return ResourceManager.GetString("Config_Traps_HideImpossible_ToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Show traps. + /// + internal static string Config_Traps_Show { + get { + return ResourceManager.GetString("Config_Traps_Show", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Undo Import. + /// + internal static string Config_UndoImport { + get { + return ResourceManager.GetString("Config_UndoImport", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your last import was on {0}, which added the trap/hoard coffer database from {1} created on {2:d}.. + /// + internal static string Config_UndoImportExplanation1 { + get { + return ResourceManager.GetString("Config_UndoImportExplanation1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If you think that was a mistake, you can remove all locations only found in the import (any location you've seen yourself is not changed).. + /// + internal static string Config_UndoImportExplanation2 { + get { + return ResourceManager.GetString("Config_UndoImportExplanation2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Upload my discoveries, show traps & coffers other players have discovered. + /// + internal static string Config_UploadMyDiscoveries_ShowOtherTraps { + get { + return ResourceManager.GetString("Config_UploadMyDiscoveries_ShowOtherTraps", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Community. + /// + internal static string ConfigTab_Community { + get { + return ResourceManager.GetString("ConfigTab_Community", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Debug. + /// + internal static string ConfigTab_Debug { + get { + return ResourceManager.GetString("ConfigTab_Debug", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Deep Dungeons. + /// + internal static string ConfigTab_DeepDungeons { + get { + return ResourceManager.GetString("ConfigTab_DeepDungeons", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Export. + /// + internal static string ConfigTab_Export { + get { + return ResourceManager.GetString("ConfigTab_Export", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import. + /// + internal static string ConfigTab_Import { + get { + return ResourceManager.GetString("ConfigTab_Import", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Renderer. + /// + internal static string ConfigTab_Renderer { + get { + return ResourceManager.GetString("ConfigTab_Renderer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not connect to server: {0}. + /// + internal static string ConnectionError_CouldNotConnectToServer { + get { + return ResourceManager.GetString("ConnectionError_CouldNotConnectToServer", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not create account ({0}).. + /// + internal static string ConnectionError_CreateAccountFailed { + get { + return ResourceManager.GetString("ConnectionError_CreateAccountFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No account-id after account was attempted to be created.. + /// + internal static string ConnectionError_CreateAccountReturnedNoId { + get { + return ResourceManager.GetString("ConnectionError_CreateAccountReturnedNoId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Invalid account id.. + /// + internal static string ConnectionError_InvalidAccountId { + get { + return ResourceManager.GetString("ConnectionError_InvalidAccountId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not log in ({0}).. + /// + internal static string ConnectionError_LoginFailed { + get { + return ResourceManager.GetString("ConnectionError_LoginFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No login information available.. + /// + internal static string ConnectionError_LoginReturnedNoToken { + get { + return ResourceManager.GetString("ConnectionError_LoginReturnedNoToken", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You are not online.. + /// + internal static string ConnectionError_NotOnline { + get { + return ResourceManager.GetString("ConnectionError_NotOnline", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer.. + /// + internal static string ConnectionError_OldVersion { + get { + return ResourceManager.GetString("ConnectionError_OldVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Connection successful.. + /// + internal static string ConnectionSuccessful { + get { + return ResourceManager.GetString("ConnectionSuccessful", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please finish the first-time setup first.. + /// + internal static string Error_FirstTimeSetupRequired { + get { + return ResourceManager.GetString("Error_FirstTimeSetupRequired", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import failed: {0}. + /// + internal static string Error_ImportFailed { + get { + return ResourceManager.GetString("Error_ImportFailed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import failed: Incompatible version.. + /// + internal static string Error_ImportFailed_IncompatibleVersion { + get { + return ResourceManager.GetString("Error_ImportFailed_IncompatibleVersion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Import failed: Invalid file.. + /// + internal static string Error_ImportFailed_InvalidFile { + get { + return ResourceManager.GetString("Error_ImportFailed_InvalidFile", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please install this plugin from the official repository at {0} to continue using it.. + /// + internal static string Error_WrongRepository { + get { + return ResourceManager.GetString("Error_WrongRepository", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Eureka Orthos. + /// + internal static string EurekaOrthos { + get { + return ResourceManager.GetString("EurekaOrthos", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pal Palace will show where potential trap & hoard coffer locations are.. + /// + internal static string Explanation_1 { + get { + return ResourceManager.GetString("Explanation_1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to To do this, using a pomander to reveal trap or treasure chest locations will save the position of what you see.. + /// + internal static string Explanation_2 { + get { + return ResourceManager.GetString("Explanation_2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ideally, we want to discover every potential trap and chest location in the game, but doing this alone is very tedious. Floor 51-60 has over 300 trap locations and over 290 coffer locations - and we don't know if that map is complete. Higher floors naturally see fewer runs, making solo attempts to map the place much harder.. + /// + internal static string Explanation_3 { + get { + return ResourceManager.GetString("Explanation_3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can decide whether you want to share traps and chests you find with the community, which likewise also will let you see chests and coffers found by other players. This can be changed at any time. No data regarding your FFXIV character or account is ever sent to our server.. + /// + internal static string Explanation_4 { + get { + return ResourceManager.GetString("Explanation_4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Heaven on High. + /// + internal static string HeavenOnHigh { + get { + return ResourceManager.GetString("HeavenOnHigh", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Imported {0} new trap locations and {1} new hoard coffer locations.. + /// + internal static string ImportCompleteStatistics { + get { + return ResourceManager.GetString("ImportCompleteStatistics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Palace Pal. + /// + internal static string Palace_Pal { + get { + return ResourceManager.GetString("Palace_Pal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Palace of the Dead. + /// + internal static string PalaceOfTheDead { + get { + return ResourceManager.GetString("PalaceOfTheDead", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save. + /// + internal static string Save { + get { + return ResourceManager.GetString("Save", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Save & Close. + /// + internal static string SaveAndClose { + get { + return ResourceManager.GetString("SaveAndClose", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Statistics. + /// + internal static string Statistics { + get { + return ResourceManager.GetString("Statistics", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Hoard. + /// + internal static string Statistics_HoardCoffers { + get { + return ResourceManager.GetString("Statistics_HoardCoffers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Instance Name. + /// + internal static string Statistics_InstanceName { + get { + return ResourceManager.GetString("Statistics_InstanceName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Id. + /// + internal static string Statistics_TerritoryId { + get { + return ResourceManager.GetString("Statistics_TerritoryId", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Traps. + /// + internal static string Statistics_Traps { + get { + return ResourceManager.GetString("Statistics_Traps", resourceCulture); + } + } + } +} diff --git a/Pal.Client/Properties/Localization.resx b/Pal.Client/Properties/Localization.resx new file mode 100644 index 0000000..b5c3045 --- /dev/null +++ b/Pal.Client/Properties/Localization.resx @@ -0,0 +1,317 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + Palace Pal + Plugin Name + + + Palace of the Dead + + + Heaven on High + + + Eureka Orthos + + + + Save + + + Save & Close + + + + + Please finish the first-time setup first. + Before using any /pal command, the first-time setup/agreeement needs to be completed. + + + Please install this plugin from the official repository at {0} to continue using it. + + + + + Open the configuration/debug window + Help text for the /pal command, shown in the Plugin Installer + + + Unknown sub-command '{0}' for '{1}'. + Error shown when using '/pal xxx' with an unknown argument 'xxx'. + + + You can view statistics for the floor you're currently on by opening the 'Debug' tab in the configuration window. + + + Unable to fetch statistics. + Shown when /pal stats produces a server-side error, and the statistics window can't be loaded. + + + Updated all locally cached marker files to latest version. + Shown after /pal update-saves was successful. + + + + + Connection successful. + + + You are not online. + Shown if you attempt to connect to the server while you have selected 'never upload discoveries, only show traps and coffers i found myself' + + + Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer. + Shown if the version is too old to create an account or log in. + + + Could not create account ({0}). + Creating an account failed with an error code, but there is no (translated) error message for it. + + + No account-id after account was attempted to be created. + If the creation of an account was successful, we expect an account-id to be returned so we can log in. If this happens, the server sent an invalid response. + + + Invalid account id. + The account id used was not found on the server. + + + Could not log in ({0}). + Logging in failed with an error code, but there is no (translated) error message for it. + + + No login information available. + The server sent no valid client token, even though the login was successful. + + + Could not connect to server: {0} + + + + + Deep Dungeons + + + Show traps + + + Trap color + + + Hide traps not on current floor + When a trap has no chance of appearing (after a pomander of safety/sight is used), hide it. + + + When using a Pomander of Sight, only the actual trap locations are visible, all other traps are hidden. +When using a Pomander of Safety, all traps are hidden. + + + Show hoard coffers + + + Hoard Coffer color + + + Hide hoard coffers not on current floor + When a hoard coffer has no chance of appearing (after a pomander of safety/sight is used), hide it. + + + When using a Pomander of intuition, only the actual hoard coffer location is visible, all other (potential) hoard coffers are hidden. + + + Show silver coffers on current floor + + + Shows all the silver coffers visible to you on the current floor. +This is not synchronized with other players and not saved between floors/runs. + + + Silver Coffer color + + + Draw filled + Whether silver coffers should only be drawn with the circle outline or as filled circle. + + + + Community + + + Test Connection + + + + Import + + + Using an export is useful if you're unable to connect to the server, or don't wish to share your findings. + + + Exports are (currently) generated manually, and they only include traps and hoard coffers encountered by 5 or more people. This may lead to higher floors having very sporadic coverage, but commonly run floors (e.g. PotD 51-60, HoH 21-30) are closer to complete. + + + If you aren't offline, importing a file won't have any noticeable effect. + + + Exports are available from {0} (as *.pal files). + + + Visit GitHub + + + File to Import: + + + Start Import + + + Your last import was on {0}, which added the trap/hoard coffer database from {1} created on {2:d}. + + + If you think that was a mistake, you can remove all locations only found in the import (any location you've seen yourself is not changed). + + + Undo Import + + + + Export + + + Export all markers from {0}: + + + Save as: + + + Start Export + + + + Renderer + Configuration tab to select Splatoon or Simple as rendering backend + + + Select which render backend to use for markers: + + + Splatoon + Splatoon plugin. Do not localize. + + + default, required Splatoon to be installed + + + Simple + + + experimental + + + Splatoon Test: + + + Draw trap & coffer circles around self + To test the Splatoon integration, you can draw markers around yourself. + + + + Debug + + + You are NOT in a deep dungeon. + + + + + Statistics + + + Id + + + Instance Name + + + Traps + + + Hoard + + + + + Pal Palace will show where potential trap & hoard coffer locations are. + + + To do this, using a pomander to reveal trap or treasure chest locations will save the position of what you see. + + + Ideally, we want to discover every potential trap and chest location in the game, but doing this alone is very tedious. Floor 51-60 has over 300 trap locations and over 290 coffer locations - and we don't know if that map is complete. Higher floors naturally see fewer runs, making solo attempts to map the place much harder. + + + You can decide whether you want to share traps and chests you find with the community, which likewise also will let you see chests and coffers found by other players. This can be changed at any time. No data regarding your FFXIV character or account is ever sent to our server. + + + Upload my discoveries, show traps & coffers other players have discovered + + + Never upload discoveries, show only traps and coffers I found myself + + + While this is not an automation feature, you're still very likely to break the ToS. + + + Other players in your party can always see where you're standing/walking. + + + As such, please avoid mentioning it in-game and do not share videos/screenshots. + + + I understand I'm using this plugin on my own risk. + + + View plugin & server source code + + + Please chose one of the options above. + Shown if neither of the two radio buttons in the first-time setup window are selected. + + + + + Imported {0} new trap locations and {1} new hoard coffer locations. + After the import of a *.pal file, the number of traps/hoard coffers is shown as a summary. + + + Import failed: {0} + + + Import failed: Incompatible version. + + + Import failed: Invalid file. + + + + diff --git a/Pal.Client/Rendering/SimpleRenderer.cs b/Pal.Client/Rendering/SimpleRenderer.cs index b204ea5..8b7c26f 100644 --- a/Pal.Client/Rendering/SimpleRenderer.cs +++ b/Pal.Client/Rendering/SimpleRenderer.cs @@ -113,7 +113,7 @@ namespace Pal.Client.Rendering public void Draw() { - if (Color == Plugin.COLOR_INVISIBLE) + if (Color == Plugin.ColorInvisible) return; switch (Type) diff --git a/Pal.Client/Scheduled/QueuedImport.cs b/Pal.Client/Scheduled/QueuedImport.cs index f8d38c1..3bc649e 100644 --- a/Pal.Client/Scheduled/QueuedImport.cs +++ b/Pal.Client/Scheduled/QueuedImport.cs @@ -6,6 +6,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; +using Pal.Client.Extensions; +using Pal.Client.Properties; namespace Pal.Client.Scheduled { @@ -56,12 +58,12 @@ namespace Pal.Client.Scheduled recreateLayout = true; saveMarkers = true; - Service.Chat.Print($"Imported {importedTraps} new trap locations and {importedHoardCoffers} new hoard coffer locations."); + Service.Chat.Print(string.Format(Localization.ImportCompleteStatistics, importedTraps, importedHoardCoffers)); } catch (Exception e) { PluginLog.Error(e, "Import failed"); - Service.Chat.PrintError($"Import failed: {e}"); + Service.Chat.PalError(string.Format(Localization.Error_ImportFailed, e)); } } @@ -69,20 +71,20 @@ namespace Pal.Client.Scheduled { if (_export.ExportVersion != ExportConfig.ExportVersion) { - Service.Chat.PrintError("Import failed: Incompatible version."); + Service.Chat.PrintError(Localization.Error_ImportFailed_IncompatibleVersion); return false; } if (!Guid.TryParse(_export.ExportId, out _exportId) || _exportId == Guid.Empty) { - Service.Chat.PrintError("Import failed: No id present."); + Service.Chat.PrintError(Localization.Error_ImportFailed_InvalidFile); return false; } if (string.IsNullOrEmpty(_export.ServerUrl)) { // If we allow for backups as import/export, this should be removed - Service.Chat.PrintError("Import failed: Unknown server."); + Service.Chat.PrintError(Localization.Error_ImportFailed_InvalidFile); return false; } diff --git a/Pal.Client/Windows/AgreementWindow.cs b/Pal.Client/Windows/AgreementWindow.cs index 1bbe6f1..a11c342 100644 --- a/Pal.Client/Windows/AgreementWindow.cs +++ b/Pal.Client/Windows/AgreementWindow.cs @@ -3,6 +3,7 @@ using Dalamud.Interface.Windowing; using ECommons; using ImGuiNET; using System.Numerics; +using Pal.Client.Properties; namespace Pal.Client.Windows { @@ -10,7 +11,7 @@ namespace Pal.Client.Windows { private int _choice; - public AgreementWindow() : base("Palace Pal###PalPalaceAgreement") + public AgreementWindow() : base($"{Localization.Palace_Pal}###PalPalaceAgreement") { Flags = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoCollapse; Size = new Vector2(500, 500); @@ -28,29 +29,29 @@ namespace Pal.Client.Windows { var config = Service.Configuration; - ImGui.TextWrapped("Pal Palace will show you via Splatoon overlays where potential trap & hoard coffer locations are."); - ImGui.TextWrapped("To do this, using a pomander to reveal trap or treasure chest locations will save the position of what you see."); + ImGui.TextWrapped(Localization.Explanation_1); + ImGui.TextWrapped(Localization.Explanation_2); ImGui.Spacing(); - ImGui.TextWrapped("Ideally, we want to discover every potential trap and chest location in the game, but doing this alone is very tedious. Floor 51-60 has over 230 trap locations and over 200 coffer locations - and we don't know if that map is complete. Higher floors naturally see fewer runs, making solo attempts to map the place much harder."); - ImGui.TextWrapped("You can decide whether you want to share traps and chests you find with the community, which likewise also will let you see chests and coffers found by other players. This can be changed at any time. No data regarding your FFXIV character or account is ever sent to our server."); + ImGui.TextWrapped(Localization.Explanation_3); + ImGui.TextWrapped(Localization.Explanation_4); - ImGui.RadioButton("Upload my discoveries, show traps & coffers other players have discovered", ref _choice, (int)Configuration.EMode.Online); - ImGui.RadioButton("Never upload discoveries, show only traps and coffers I found myself", ref _choice, (int)Configuration.EMode.Offline); + ImGui.RadioButton(Localization.Config_UploadMyDiscoveries_ShowOtherTraps, ref _choice, (int)Configuration.EMode.Online); + ImGui.RadioButton(Localization.Config_NeverUploadDiscoveries_ShowMyTraps, ref _choice, (int)Configuration.EMode.Offline); ImGui.Separator(); - ImGui.TextColored(ImGuiColors.DalamudRed, "While this is not an automation feature, you're still very likely to break the ToS."); - ImGui.TextColored(ImGuiColors.DalamudRed, "Other players in your party can always see where you're standing/walking."); - ImGui.TextColored(ImGuiColors.DalamudRed, "As such, please avoid mentioning it in-game and do not share videos/screenshots."); + ImGui.TextColored(ImGuiColors.DalamudRed, Localization.Agreement_Warning1); + ImGui.TextColored(ImGuiColors.DalamudRed, Localization.Agreement_Warning2); + ImGui.TextColored(ImGuiColors.DalamudRed, Localization.Agreement_Warning3); ImGui.Separator(); if (_choice == -1) - ImGui.TextDisabled("Please chose one of the options above."); + ImGui.TextDisabled(Localization.Agreement_PickOneOption); ImGui.BeginDisabled(_choice == -1); - if (ImGui.Button("I understand I'm using this plugin on my own risk.")) + if (ImGui.Button(Localization.Agreement_UsingThisOnMyOwnRisk)) { config.Mode = (Configuration.EMode)_choice; config.FirstUse = false; @@ -62,7 +63,7 @@ namespace Pal.Client.Windows ImGui.Separator(); - if (ImGui.Button("View plugin & server source code")) + if (ImGui.Button(Localization.Agreement_ViewPluginAndServerSourceCode)) GenericHelpers.ShellStart("https://github.com/LizaCarvbelli/PalPalace"); } } diff --git a/Pal.Client/Windows/ConfigWindow.cs b/Pal.Client/Windows/ConfigWindow.cs index 77bdd37..5c9628c 100644 --- a/Pal.Client/Windows/ConfigWindow.cs +++ b/Pal.Client/Windows/ConfigWindow.cs @@ -5,24 +5,20 @@ using Dalamud.Interface.ImGuiFileDialog; using Dalamud.Interface.Windowing; using Dalamud.Logging; using ECommons; -using ECommons.Reflection; -using ECommons.SplatoonAPI; using Google.Protobuf; using ImGuiNET; using Pal.Client.Net; using Pal.Client.Rendering; using Pal.Client.Scheduled; using System; -using System.Collections; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; -using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; +using Pal.Client.Properties; namespace Pal.Client.Windows { @@ -49,10 +45,10 @@ namespace Pal.Client.Windows private FileDialogManager _importDialog; private FileDialogManager _exportDialog; - public ConfigWindow() : base("Palace Pal###PalPalaceConfig") + public ConfigWindow() : base($"{Localization.Palace_Pal}###PalPalaceConfig") { var version = typeof(Plugin).Assembly.GetName().Version!.ToString(2); - WindowName = $"Palace Pal v{version}###PalPalaceConfig"; + WindowName = $"{Localization.Palace_Pal} v{version}###PalPalaceConfig"; Size = new Vector2(500, 400); SizeCondition = ImGuiCond.FirstUseEver; Position = new Vector2(300, 300); @@ -91,7 +87,7 @@ namespace Pal.Client.Windows bool saveAndClose = false; if (ImGui.BeginTabBar("PalTabs")) { - DrawTrapCofferTab(ref save, ref saveAndClose); + DrawDeepDungeonItemsTab(ref save, ref saveAndClose); DrawCommunityTab(ref saveAndClose); DrawImportTab(); DrawExportTab(); @@ -124,51 +120,51 @@ namespace Pal.Client.Windows } } - private void DrawTrapCofferTab(ref bool save, ref bool saveAndClose) + private void DrawDeepDungeonItemsTab(ref bool save, ref bool saveAndClose) { - if (ImGui.BeginTabItem("PotD/HoH")) + if (ImGui.BeginTabItem(Localization.ConfigTab_DeepDungeons)) { - ImGui.Checkbox("Show traps", ref _showTraps); + ImGui.Checkbox(Localization.Config_Traps_Show, ref _showTraps); ImGui.Indent(); ImGui.BeginDisabled(!_showTraps); ImGui.Spacing(); - ImGui.ColorEdit4("Trap color", ref _trapColor, ImGuiColorEditFlags.NoInputs); - ImGui.Checkbox("Hide traps not on current floor", ref _onlyVisibleTrapsAfterPomander); + ImGui.ColorEdit4(Localization.Config_Traps_Color, ref _trapColor, ImGuiColorEditFlags.NoInputs); + ImGui.Checkbox(Localization.Config_Traps_HideImpossible, ref _onlyVisibleTrapsAfterPomander); ImGui.SameLine(); - ImGuiComponents.HelpMarker("When using a Pomander of sight, only the actual trap locations are visible, all other traps are hidden."); + ImGuiComponents.HelpMarker(Localization.Config_Traps_HideImpossible_ToolTip); ImGui.EndDisabled(); ImGui.Unindent(); ImGui.Separator(); - ImGui.Checkbox("Show hoard coffers", ref _showHoard); + ImGui.Checkbox(Localization.Config_HoardCoffers_Show, ref _showHoard); ImGui.Indent(); ImGui.BeginDisabled(!_showHoard); ImGui.Spacing(); - ImGui.ColorEdit4("Hoard Coffer color", ref _hoardColor, ImGuiColorEditFlags.NoInputs); - ImGui.Checkbox("Hide hoard coffers not on current floor", ref _onlyVisibleHoardAfterPomander); + ImGui.ColorEdit4(Localization.Config_HoardCoffers_Color, ref _hoardColor, ImGuiColorEditFlags.NoInputs); + ImGui.Checkbox(Localization.Config_HoardCoffers_HideImpossible, ref _onlyVisibleHoardAfterPomander); ImGui.SameLine(); - ImGuiComponents.HelpMarker("When using a Pomander of intuition, only the actual hoard coffer location is visible, all other (potential) hoard coffers are hidden."); + ImGuiComponents.HelpMarker(Localization.Config_HoardCoffers_HideImpossible_ToolTip); ImGui.EndDisabled(); ImGui.Unindent(); ImGui.Separator(); - ImGui.Checkbox("Show silver coffers on current floor", ref _showSilverCoffers); - ImGuiComponents.HelpMarker("Shows all the silver coffers visible to you on the current floor.\nThis is not synchronized with other players and not saved between floors/runs."); + ImGui.Checkbox(Localization.Config_SilverCoffer_Show, ref _showSilverCoffers); + ImGuiComponents.HelpMarker(Localization.Config_SilverCoffers_ToolTip); ImGui.Indent(); ImGui.BeginDisabled(!_showSilverCoffers); ImGui.Spacing(); - ImGui.ColorEdit4("Silver Coffer color", ref _silverCofferColor, ImGuiColorEditFlags.NoInputs); - ImGui.Checkbox("Draw filled", ref _fillSilverCoffers); + ImGui.ColorEdit4(Localization.Config_SilverCoffer_Color, ref _silverCofferColor, ImGuiColorEditFlags.NoInputs); + ImGui.Checkbox(Localization.Config_SilverCoffer_Filled, ref _fillSilverCoffers); ImGui.EndDisabled(); ImGui.Unindent(); ImGui.Separator(); - save = ImGui.Button("Save"); + save = ImGui.Button(Localization.Save); ImGui.SameLine(); - saveAndClose = ImGui.Button("Save & Close"); + saveAndClose = ImGui.Button(Localization.SaveAndClose); ImGui.EndTabItem(); } @@ -176,21 +172,21 @@ namespace Pal.Client.Windows private void DrawCommunityTab(ref bool saveAndClose) { - if (BeginTabItemEx("Community", _switchToCommunityTab ? ImGuiTabItemFlags.SetSelected : ImGuiTabItemFlags.None)) + if (BeginTabItemEx(Localization.ConfigTab_Community, _switchToCommunityTab ? ImGuiTabItemFlags.SetSelected : ImGuiTabItemFlags.None)) { _switchToCommunityTab = false; - ImGui.TextWrapped("Ideally, we want to discover every potential trap and chest location in the game, but doing this alone is very tedious. Floor 51-60 has over 230 trap locations and over 200 coffer locations - and we don't know if that map is complete. Higher floors naturally see fewer runs, making solo attempts to map the place much harder."); - ImGui.TextWrapped("You can decide whether you want to share traps and chests you find with the community, which likewise also will let you see chests and coffers found by other players. This can be changed at any time. No data regarding your FFXIV character or account is ever sent to our server."); + ImGui.TextWrapped(Localization.Explanation_3); + ImGui.TextWrapped(Localization.Explanation_4); - ImGui.RadioButton("Upload my discoveries, show traps & coffers other players have discovered", ref _mode, (int)Configuration.EMode.Online); - ImGui.RadioButton("Never upload discoveries, show only traps and coffers I found myself", ref _mode, (int)Configuration.EMode.Offline); - saveAndClose = ImGui.Button("Save & Close"); + ImGui.RadioButton(Localization.Config_UploadMyDiscoveries_ShowOtherTraps, ref _mode, (int)Configuration.EMode.Online); + ImGui.RadioButton(Localization.Config_NeverUploadDiscoveries_ShowMyTraps, ref _mode, (int)Configuration.EMode.Offline); + saveAndClose = ImGui.Button(Localization.SaveAndClose); ImGui.Separator(); ImGui.BeginDisabled(Service.Configuration.Mode != Configuration.EMode.Online); - if (ImGui.Button("Test Connection")) + if (ImGui.Button(Localization.Config_TestConnection)) TestConnection(); if (_connectionText != null) @@ -203,23 +199,23 @@ namespace Pal.Client.Windows private void DrawImportTab() { - if (ImGui.BeginTabItem("Import")) + if (ImGui.BeginTabItem(Localization.ConfigTab_Import)) { - ImGui.TextWrapped("Using an export is useful if you're unable to connect to the server, or don't wish to share your findings."); - ImGui.TextWrapped("Exports are (currently) generated manually, and they only include traps and hoard coffers encountered by 5 or more people. This may lead to higher floors having very sporadic coverage, but commonly run floors (e.g. PotD 51-60, HoH 21-30) are closer to complete."); - ImGui.TextWrapped("If you aren't offline, importing a file won't have any noticeable effect."); + ImGui.TextWrapped(Localization.Config_ImportExplanation1); + ImGui.TextWrapped(Localization.Config_ImportExplanation2); + ImGui.TextWrapped(Localization.Config_ImportExplanation3); ImGui.Separator(); - ImGui.TextWrapped("Exports are available from https://github.com/carvelli/PalacePal/releases/ (as *.pal files)."); - if (ImGui.Button("Visit GitHub")) + ImGui.TextWrapped(string.Format(Localization.Config_ImportDownloadLocation, "https://github.com/carvelli/PalacePal/releases/")); + if (ImGui.Button(Localization.Config_Import_VisitGitHub)) GenericHelpers.ShellStart("https://github.com/carvelli/PalacePal/releases/latest"); ImGui.Separator(); - ImGui.Text("File to Import:"); + ImGui.Text(Localization.Config_SelectImportFile); ImGui.SameLine(); ImGui.InputTextWithHint("", "Path to *.pal file", ref _openImportPath, 260); ImGui.SameLine(); if (ImGuiComponents.IconButton(FontAwesomeIcon.Search)) { - _importDialog.OpenFileDialog("Palace Pal - Import", "Palace Pal (*.pal) {.pal}", (success, paths) => + _importDialog.OpenFileDialog(Localization.Palace_Pal, $"{Localization.Palace_Pal} (*.pal) {{.pal}}", (success, paths) => { if (success && paths.Count == 1) { @@ -230,7 +226,7 @@ namespace Pal.Client.Windows } ImGui.BeginDisabled(string.IsNullOrEmpty(_openImportPath) || !File.Exists(_openImportPath)); - if (ImGui.Button("Start Import")) + if (ImGui.Button(Localization.Config_StartImport)) DoImport(_openImportPath); ImGui.EndDisabled(); @@ -238,9 +234,9 @@ namespace Pal.Client.Windows if (importHistory != null) { ImGui.Separator(); - ImGui.TextWrapped($"Your last import was on {importHistory.ImportedAt}, which added the trap/hoard coffer database from {importHistory.RemoteUrl} created on {importHistory.ExportedAt:d}."); - ImGui.TextWrapped("If you think that was a mistake, you can remove all locations only found in the import (any location you've seen yourself is not changed)."); - if (ImGui.Button("Undo Import")) + ImGui.TextWrapped(string.Format(Localization.Config_UndoImportExplanation1, importHistory.ImportedAt, importHistory.RemoteUrl, importHistory.ExportedAt)); + ImGui.TextWrapped(Localization.Config_UndoImportExplanation2); + if (ImGui.Button(Localization.Config_UndoImport)) UndoImport(importHistory.Id); } @@ -250,20 +246,20 @@ namespace Pal.Client.Windows private void DrawExportTab() { - if (Service.RemoteApi.HasRoleOnCurrentServer("export:run") && ImGui.BeginTabItem("Export")) + if (Service.RemoteApi.HasRoleOnCurrentServer("export:run") && ImGui.BeginTabItem(Localization.ConfigTab_Export)) { string todaysFileName = $"export-{DateTime.Today:yyyy-MM-dd}.pal"; if (string.IsNullOrEmpty(_saveExportPath) && !string.IsNullOrEmpty(_saveExportDialogStartPath)) _saveExportPath = Path.Join(_saveExportDialogStartPath, todaysFileName); - ImGui.TextWrapped($"Export all markers from {RemoteApi.RemoteUrl}:"); - ImGui.Text("Save as:"); + ImGui.TextWrapped(string.Format(Localization.Config_ExportSource, RemoteApi.RemoteUrl)); + ImGui.Text(Localization.Config_Export_SaveAs); ImGui.SameLine(); ImGui.InputTextWithHint("", "Path to *.pal file", ref _saveExportPath, 260); ImGui.SameLine(); if (ImGuiComponents.IconButton(FontAwesomeIcon.Search)) { - _importDialog.SaveFileDialog("Palace Pal - Export", "Palace Pal (*.pal) {.pal}", todaysFileName, "pal", (success, path) => + _importDialog.SaveFileDialog(Localization.Palace_Pal, $"{Localization.Palace_Pal} (*.pal) {{.pal}}", todaysFileName, "pal", (success, path) => { if (success && !string.IsNullOrEmpty(path)) { @@ -274,7 +270,7 @@ namespace Pal.Client.Windows } ImGui.BeginDisabled(string.IsNullOrEmpty(_saveExportPath) || File.Exists(_saveExportPath)); - if (ImGui.Button("Start Export")) + if (ImGui.Button(Localization.Config_StartExport)) DoExport(_saveExportPath); ImGui.EndDisabled(); @@ -284,22 +280,22 @@ namespace Pal.Client.Windows private void DrawRenderTab(ref bool save, ref bool saveAndClose) { - if (ImGui.BeginTabItem("Renderer")) + if (ImGui.BeginTabItem(Localization.ConfigTab_Renderer)) { - ImGui.Text("Select which render backend to use for markers:"); - ImGui.RadioButton("Splatoon (default, required Splatoon to be installed)", ref _renderer, (int)Configuration.ERenderer.Splatoon); - ImGui.RadioButton("Simple (experimental)", ref _renderer, (int)Configuration.ERenderer.Simple); + ImGui.Text(Localization.Config_SelectRenderBackend); + ImGui.RadioButton($"{Localization.Config_Renderer_Splatoon} ({Localization.Config_Renderer_Splatoon_Hint})", ref _renderer, (int)Configuration.ERenderer.Splatoon); + ImGui.RadioButton($"{Localization.Config_Renderer_Simple} ({Localization.Config_Renderer_Simple_Hint})", ref _renderer, (int)Configuration.ERenderer.Simple); ImGui.Separator(); - save = ImGui.Button("Save"); + save = ImGui.Button(Localization.Save); ImGui.SameLine(); - saveAndClose = ImGui.Button("Save & Close"); + saveAndClose = ImGui.Button(Localization.SaveAndClose); ImGui.Separator(); - ImGui.Text("Splatoon Test:"); + ImGui.Text(Localization.Config_Splatoon_Test); ImGui.BeginDisabled(!(Service.Plugin.Renderer is IDrawDebugItems)); - if (ImGui.Button("Draw trap & coffer circles around self")) + if (ImGui.Button(Localization.Config_Splatoon_DrawCircles)) (Service.Plugin.Renderer as IDrawDebugItems)?.DrawDebugItems(_trapColor, _hoardColor); ImGui.EndDisabled(); @@ -309,7 +305,7 @@ namespace Pal.Client.Windows private void DrawDebugTab() { - if (ImGui.BeginTabItem("Debug")) + if (ImGui.BeginTabItem(Localization.ConfigTab_Debug)) { var plugin = Service.Plugin; if (plugin.IsInDeepDungeon()) @@ -346,7 +342,7 @@ namespace Pal.Client.Windows ImGui.TextWrapped("Traps and coffers may not be discovered even after using a pomander if they're far away (around 1,5-2 rooms)."); } else - ImGui.Text("You are NOT in a deep dungeon."); + ImGui.Text(Localization.Config_Debug_NotInADeepDungeon); ImGui.EndTabItem(); } diff --git a/Pal.Client/Windows/StatisticsWindow.cs b/Pal.Client/Windows/StatisticsWindow.cs index 7de6b3f..58afee1 100644 --- a/Pal.Client/Windows/StatisticsWindow.cs +++ b/Pal.Client/Windows/StatisticsWindow.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Numerics; using System.Text; using System.Threading.Tasks; +using Pal.Client.Properties; namespace Pal.Client.Windows { @@ -17,7 +18,7 @@ namespace Pal.Client.Windows { private SortedDictionary _territoryStatistics = new(); - public StatisticsWindow() : base("Palace Pal - Statistics###PalacePalStats") + public StatisticsWindow() : base($"{Localization.Palace_Pal} - {Localization.Statistics}###PalacePalStats") { Size = new Vector2(500, 500); SizeCondition = ImGuiCond.FirstUseEver; @@ -33,8 +34,8 @@ namespace Pal.Client.Windows { if (ImGui.BeginTabBar("Tabs")) { - DrawDungeonStats("Palace of the Dead", ETerritoryType.Palace_1_10, ETerritoryType.Palace_191_200); - DrawDungeonStats("Heaven on High", ETerritoryType.HeavenOnHigh_1_10, ETerritoryType.HeavenOnHigh_91_100); + DrawDungeonStats(Localization.PalaceOfTheDead, ETerritoryType.Palace_1_10, ETerritoryType.Palace_191_200); + DrawDungeonStats(Localization.HeavenOnHigh, ETerritoryType.HeavenOnHigh_1_10, ETerritoryType.HeavenOnHigh_91_100); } } @@ -44,10 +45,10 @@ namespace Pal.Client.Windows { if (ImGui.BeginTable($"TrapHoardStatistics{name}", 4, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable)) { - ImGui.TableSetupColumn("Id"); - ImGui.TableSetupColumn("Instance"); - ImGui.TableSetupColumn("Traps"); - ImGui.TableSetupColumn("Hoard"); + ImGui.TableSetupColumn(Localization.Statistics_TerritoryId); + ImGui.TableSetupColumn(Localization.Statistics_InstanceName); + ImGui.TableSetupColumn(Localization.Statistics_Traps); + ImGui.TableSetupColumn(Localization.Statistics_HoardCoffers); ImGui.TableHeadersRow(); foreach (var (territoryType, stats) in _territoryStatistics.Where(x => x.Key >= minTerritory && x.Key <= maxTerritory))