Move language strings into resx file

rendering
Liza 2023-02-10 20:48:14 +01:00
parent 01d6b7f2dd
commit f7840ab29b
19 changed files with 1328 additions and 154 deletions

22
.github/workflows/upload-crowdin.yml vendored Normal file
View File

@ -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 }}

View File

@ -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.
/// </summary>
public List<string> CachedRoles { get; set; } = new List<string>();
public List<string> 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)

View File

@ -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

View File

@ -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}");
}

View File

@ -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<T>(this WindowSystem windowSystem)
where T : Window
{
return windowSystem.Windows.Select(w => w as T).FirstOrDefault(w => w != null);
return windowSystem.Windows.OfType<T>().FirstOrDefault();
}
}
}

View File

@ -13,8 +13,8 @@ namespace Pal.Client
/// </summary>
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<Marker> 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<Marker>(JsonSerializer.Deserialize<HashSet<Marker>>(content, _jsonSerializerOptions) ?? new()),
Markers = new ConcurrentBag<Marker>(JsonSerializer.Deserialize<HashSet<Marker>>(content, JsonSerializerOptions) ?? new()),
};
}
else
{
var save = JsonSerializer.Deserialize<SaveFile>(content, _jsonSerializerOptions);
var save = JsonSerializer.Deserialize<SaveFile>(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<Marker>(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

View File

@ -17,7 +17,7 @@ namespace Pal.Client
/// <summary>
/// Whether we have encountered the trap/coffer at this location in-game.
/// </summary>
public bool Seen { get; set; } = false;
public bool Seen { get; set; }
/// <summary>
/// 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).
/// </summary>
public List<string> RemoteSeenOn { get; set; } = new List<string>();
public List<string> RemoteSeenOn { get; set; } = new();
/// <summary>
/// Whether this marker was requested to be seen, to avoid duplicate requests.
/// </summary>
[JsonIgnore]
public bool RemoteSeenRequested { get; set; } = false;
public bool RemoteSeenRequested { get; set; }
/// <summary>
/// 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.
/// </summary>
public List<Guid> Imports { get; set; } = new List<Guid>();
public List<Guid> Imports { get; set; } = new();
public bool WasImported { get; set; }

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -28,6 +28,10 @@
<ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')">
<EmbeddedResource Include="Certificate.pfx" />
<EmbeddedResource Update="Properties\Localization.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Localization.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
@ -85,6 +89,14 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Localization.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Localization.resx</DependentUpon>
</Compile>
</ItemGroup>
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin">
<Exec Command="rename &quot;$(OutDir)$(AssemblyName)\latest.zip&quot; &quot;$(AssemblyName)-$(Version).zip&quot;" />
</Target>

View File

@ -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<nint> 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<Marker> 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<Marker> 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<IRenderElement> 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)

View File

@ -0,0 +1,811 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Pal.Client.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Please chose one of the options above..
/// </summary>
internal static string Agreement_PickOneOption {
get {
return ResourceManager.GetString("Agreement_PickOneOption", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to I understand I&apos;m using this plugin on my own risk..
/// </summary>
internal static string Agreement_UsingThisOnMyOwnRisk {
get {
return ResourceManager.GetString("Agreement_UsingThisOnMyOwnRisk", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to View plugin &amp; server source code.
/// </summary>
internal static string Agreement_ViewPluginAndServerSourceCode {
get {
return ResourceManager.GetString("Agreement_ViewPluginAndServerSourceCode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to While this is not an automation feature, you&apos;re still very likely to break the ToS..
/// </summary>
internal static string Agreement_Warning1 {
get {
return ResourceManager.GetString("Agreement_Warning1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Other players in your party can always see where you&apos;re standing/walking..
/// </summary>
internal static string Agreement_Warning2 {
get {
return ResourceManager.GetString("Agreement_Warning2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to As such, please avoid mentioning it in-game and do not share videos/screenshots..
/// </summary>
internal static string Agreement_Warning3 {
get {
return ResourceManager.GetString("Agreement_Warning3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open the configuration/debug window.
/// </summary>
internal static string Command_pal_HelpText {
get {
return ResourceManager.GetString("Command_pal_HelpText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You can view statistics for the floor you&apos;re currently on by opening the &apos;Debug&apos; tab in the configuration window..
/// </summary>
internal static string Command_pal_stats_CurrentFloor {
get {
return ResourceManager.GetString("Command_pal_stats_CurrentFloor", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unable to fetch statistics..
/// </summary>
internal static string Command_pal_stats_UnableToFetchStatistics {
get {
return ResourceManager.GetString("Command_pal_stats_UnableToFetchStatistics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unknown sub-command &apos;{0}&apos; for &apos;{1}&apos;..
/// </summary>
internal static string Command_pal_UnknownSubcommand {
get {
return ResourceManager.GetString("Command_pal_UnknownSubcommand", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Updated all locally cached marker files to latest version..
/// </summary>
internal static string Command_pal_updatesaves {
get {
return ResourceManager.GetString("Command_pal_updatesaves", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You are NOT in a deep dungeon..
/// </summary>
internal static string Config_Debug_NotInADeepDungeon {
get {
return ResourceManager.GetString("Config_Debug_NotInADeepDungeon", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Save as:.
/// </summary>
internal static string Config_Export_SaveAs {
get {
return ResourceManager.GetString("Config_Export_SaveAs", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export all markers from {0}:.
/// </summary>
internal static string Config_ExportSource {
get {
return ResourceManager.GetString("Config_ExportSource", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hoard Coffer color.
/// </summary>
internal static string Config_HoardCoffers_Color {
get {
return ResourceManager.GetString("Config_HoardCoffers_Color", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hide hoard coffers not on current floor.
/// </summary>
internal static string Config_HoardCoffers_HideImpossible {
get {
return ResourceManager.GetString("Config_HoardCoffers_HideImpossible", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Config_HoardCoffers_HideImpossible_ToolTip {
get {
return ResourceManager.GetString("Config_HoardCoffers_HideImpossible_ToolTip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show hoard coffers.
/// </summary>
internal static string Config_HoardCoffers_Show {
get {
return ResourceManager.GetString("Config_HoardCoffers_Show", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Visit GitHub.
/// </summary>
internal static string Config_Import_VisitGitHub {
get {
return ResourceManager.GetString("Config_Import_VisitGitHub", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exports are available from {0} (as *.pal files)..
/// </summary>
internal static string Config_ImportDownloadLocation {
get {
return ResourceManager.GetString("Config_ImportDownloadLocation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Using an export is useful if you&apos;re unable to connect to the server, or don&apos;t wish to share your findings..
/// </summary>
internal static string Config_ImportExplanation1 {
get {
return ResourceManager.GetString("Config_ImportExplanation1", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Config_ImportExplanation2 {
get {
return ResourceManager.GetString("Config_ImportExplanation2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to If you aren&apos;t offline, importing a file won&apos;t have any noticeable effect..
/// </summary>
internal static string Config_ImportExplanation3 {
get {
return ResourceManager.GetString("Config_ImportExplanation3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Never upload discoveries, show only traps and coffers I found myself.
/// </summary>
internal static string Config_NeverUploadDiscoveries_ShowMyTraps {
get {
return ResourceManager.GetString("Config_NeverUploadDiscoveries_ShowMyTraps", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Simple.
/// </summary>
internal static string Config_Renderer_Simple {
get {
return ResourceManager.GetString("Config_Renderer_Simple", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to experimental.
/// </summary>
internal static string Config_Renderer_Simple_Hint {
get {
return ResourceManager.GetString("Config_Renderer_Simple_Hint", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Splatoon.
/// </summary>
internal static string Config_Renderer_Splatoon {
get {
return ResourceManager.GetString("Config_Renderer_Splatoon", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to default, required Splatoon to be installed.
/// </summary>
internal static string Config_Renderer_Splatoon_Hint {
get {
return ResourceManager.GetString("Config_Renderer_Splatoon_Hint", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to File to Import:.
/// </summary>
internal static string Config_SelectImportFile {
get {
return ResourceManager.GetString("Config_SelectImportFile", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Select which render backend to use for markers:.
/// </summary>
internal static string Config_SelectRenderBackend {
get {
return ResourceManager.GetString("Config_SelectRenderBackend", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Silver Coffer color.
/// </summary>
internal static string Config_SilverCoffer_Color {
get {
return ResourceManager.GetString("Config_SilverCoffer_Color", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Draw filled.
/// </summary>
internal static string Config_SilverCoffer_Filled {
get {
return ResourceManager.GetString("Config_SilverCoffer_Filled", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show silver coffers on current floor.
/// </summary>
internal static string Config_SilverCoffer_Show {
get {
return ResourceManager.GetString("Config_SilverCoffer_Show", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Config_SilverCoffers_ToolTip {
get {
return ResourceManager.GetString("Config_SilverCoffers_ToolTip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Draw trap &amp; coffer circles around self.
/// </summary>
internal static string Config_Splatoon_DrawCircles {
get {
return ResourceManager.GetString("Config_Splatoon_DrawCircles", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Splatoon Test:.
/// </summary>
internal static string Config_Splatoon_Test {
get {
return ResourceManager.GetString("Config_Splatoon_Test", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Start Export.
/// </summary>
internal static string Config_StartExport {
get {
return ResourceManager.GetString("Config_StartExport", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Start Import.
/// </summary>
internal static string Config_StartImport {
get {
return ResourceManager.GetString("Config_StartImport", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Test Connection.
/// </summary>
internal static string Config_TestConnection {
get {
return ResourceManager.GetString("Config_TestConnection", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Trap color.
/// </summary>
internal static string Config_Traps_Color {
get {
return ResourceManager.GetString("Config_Traps_Color", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hide traps not on current floor.
/// </summary>
internal static string Config_Traps_HideImpossible {
get {
return ResourceManager.GetString("Config_Traps_HideImpossible", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Config_Traps_HideImpossible_ToolTip {
get {
return ResourceManager.GetString("Config_Traps_HideImpossible_ToolTip", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show traps.
/// </summary>
internal static string Config_Traps_Show {
get {
return ResourceManager.GetString("Config_Traps_Show", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Undo Import.
/// </summary>
internal static string Config_UndoImport {
get {
return ResourceManager.GetString("Config_UndoImport", resourceCulture);
}
}
/// <summary>
/// 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}..
/// </summary>
internal static string Config_UndoImportExplanation1 {
get {
return ResourceManager.GetString("Config_UndoImportExplanation1", resourceCulture);
}
}
/// <summary>
/// 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&apos;ve seen yourself is not changed)..
/// </summary>
internal static string Config_UndoImportExplanation2 {
get {
return ResourceManager.GetString("Config_UndoImportExplanation2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Upload my discoveries, show traps &amp; coffers other players have discovered.
/// </summary>
internal static string Config_UploadMyDiscoveries_ShowOtherTraps {
get {
return ResourceManager.GetString("Config_UploadMyDiscoveries_ShowOtherTraps", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Community.
/// </summary>
internal static string ConfigTab_Community {
get {
return ResourceManager.GetString("ConfigTab_Community", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Debug.
/// </summary>
internal static string ConfigTab_Debug {
get {
return ResourceManager.GetString("ConfigTab_Debug", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Deep Dungeons.
/// </summary>
internal static string ConfigTab_DeepDungeons {
get {
return ResourceManager.GetString("ConfigTab_DeepDungeons", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export.
/// </summary>
internal static string ConfigTab_Export {
get {
return ResourceManager.GetString("ConfigTab_Export", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import.
/// </summary>
internal static string ConfigTab_Import {
get {
return ResourceManager.GetString("ConfigTab_Import", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Renderer.
/// </summary>
internal static string ConfigTab_Renderer {
get {
return ResourceManager.GetString("ConfigTab_Renderer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not connect to server: {0}.
/// </summary>
internal static string ConnectionError_CouldNotConnectToServer {
get {
return ResourceManager.GetString("ConnectionError_CouldNotConnectToServer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not create account ({0})..
/// </summary>
internal static string ConnectionError_CreateAccountFailed {
get {
return ResourceManager.GetString("ConnectionError_CreateAccountFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No account-id after account was attempted to be created..
/// </summary>
internal static string ConnectionError_CreateAccountReturnedNoId {
get {
return ResourceManager.GetString("ConnectionError_CreateAccountReturnedNoId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid account id..
/// </summary>
internal static string ConnectionError_InvalidAccountId {
get {
return ResourceManager.GetString("ConnectionError_InvalidAccountId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Could not log in ({0})..
/// </summary>
internal static string ConnectionError_LoginFailed {
get {
return ResourceManager.GetString("ConnectionError_LoginFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No login information available..
/// </summary>
internal static string ConnectionError_LoginReturnedNoToken {
get {
return ResourceManager.GetString("ConnectionError_LoginReturnedNoToken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You are not online..
/// </summary>
internal static string ConnectionError_NotOnline {
get {
return ResourceManager.GetString("ConnectionError_NotOnline", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer..
/// </summary>
internal static string ConnectionError_OldVersion {
get {
return ResourceManager.GetString("ConnectionError_OldVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Connection successful..
/// </summary>
internal static string ConnectionSuccessful {
get {
return ResourceManager.GetString("ConnectionSuccessful", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please finish the first-time setup first..
/// </summary>
internal static string Error_FirstTimeSetupRequired {
get {
return ResourceManager.GetString("Error_FirstTimeSetupRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import failed: {0}.
/// </summary>
internal static string Error_ImportFailed {
get {
return ResourceManager.GetString("Error_ImportFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import failed: Incompatible version..
/// </summary>
internal static string Error_ImportFailed_IncompatibleVersion {
get {
return ResourceManager.GetString("Error_ImportFailed_IncompatibleVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import failed: Invalid file..
/// </summary>
internal static string Error_ImportFailed_InvalidFile {
get {
return ResourceManager.GetString("Error_ImportFailed_InvalidFile", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please install this plugin from the official repository at {0} to continue using it..
/// </summary>
internal static string Error_WrongRepository {
get {
return ResourceManager.GetString("Error_WrongRepository", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Eureka Orthos.
/// </summary>
internal static string EurekaOrthos {
get {
return ResourceManager.GetString("EurekaOrthos", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pal Palace will show where potential trap &amp; hoard coffer locations are..
/// </summary>
internal static string Explanation_1 {
get {
return ResourceManager.GetString("Explanation_1", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Explanation_2 {
get {
return ResourceManager.GetString("Explanation_2", resourceCulture);
}
}
/// <summary>
/// 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&apos;t know if that map is complete. Higher floors naturally see fewer runs, making solo attempts to map the place much harder..
/// </summary>
internal static string Explanation_3 {
get {
return ResourceManager.GetString("Explanation_3", resourceCulture);
}
}
/// <summary>
/// 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..
/// </summary>
internal static string Explanation_4 {
get {
return ResourceManager.GetString("Explanation_4", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Heaven on High.
/// </summary>
internal static string HeavenOnHigh {
get {
return ResourceManager.GetString("HeavenOnHigh", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Imported {0} new trap locations and {1} new hoard coffer locations..
/// </summary>
internal static string ImportCompleteStatistics {
get {
return ResourceManager.GetString("ImportCompleteStatistics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Palace Pal.
/// </summary>
internal static string Palace_Pal {
get {
return ResourceManager.GetString("Palace_Pal", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Palace of the Dead.
/// </summary>
internal static string PalaceOfTheDead {
get {
return ResourceManager.GetString("PalaceOfTheDead", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Save.
/// </summary>
internal static string Save {
get {
return ResourceManager.GetString("Save", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Save &amp; Close.
/// </summary>
internal static string SaveAndClose {
get {
return ResourceManager.GetString("SaveAndClose", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Statistics.
/// </summary>
internal static string Statistics {
get {
return ResourceManager.GetString("Statistics", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hoard.
/// </summary>
internal static string Statistics_HoardCoffers {
get {
return ResourceManager.GetString("Statistics_HoardCoffers", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Instance Name.
/// </summary>
internal static string Statistics_InstanceName {
get {
return ResourceManager.GetString("Statistics_InstanceName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Id.
/// </summary>
internal static string Statistics_TerritoryId {
get {
return ResourceManager.GetString("Statistics_TerritoryId", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Traps.
/// </summary>
internal static string Statistics_Traps {
get {
return ResourceManager.GetString("Statistics_Traps", resourceCulture);
}
}
}
}

View File

@ -0,0 +1,317 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<!-- Common -->
<data name="Palace_Pal" xml:space="preserve">
<value>Palace Pal</value>
<comment>Plugin Name</comment>
</data>
<data name="PalaceOfTheDead" xml:space="preserve">
<value>Palace of the Dead</value>
</data>
<data name="HeavenOnHigh" xml:space="preserve">
<value>Heaven on High</value>
</data>
<data name="EurekaOrthos" xml:space="preserve">
<value>Eureka Orthos</value>
</data>
<data name="Save" xml:space="preserve">
<value>Save</value>
</data>
<data name="SaveAndClose" xml:space="preserve">
<value>Save &amp; Close</value>
</data>
<!-- Generic Errors -->
<data name="Error_FirstTimeSetupRequired" xml:space="preserve">
<value>Please finish the first-time setup first.</value>
<comment>Before using any /pal command, the first-time setup/agreeement needs to be completed.</comment>
</data>
<data name="Error_WrongRepository" xml:space="preserve">
<value>Please install this plugin from the official repository at {0} to continue using it.</value>
</data>
<!-- /pal commands -->
<data name="Command_pal_HelpText" xml:space="preserve">
<value>Open the configuration/debug window</value>
<comment>Help text for the /pal command, shown in the Plugin Installer</comment>
</data>
<data name="Command_pal_UnknownSubcommand" xml:space="preserve">
<value>Unknown sub-command '{0}' for '{1}'.</value>
<comment>Error shown when using '/pal xxx' with an unknown argument 'xxx'.</comment>
</data>
<data name="Command_pal_stats_CurrentFloor" xml:space="preserve">
<value>You can view statistics for the floor you're currently on by opening the 'Debug' tab in the configuration window.</value>
</data>
<data name="Command_pal_stats_UnableToFetchStatistics" xml:space="preserve">
<value>Unable to fetch statistics.</value>
<comment>Shown when /pal stats produces a server-side error, and the statistics window can't be loaded.</comment>
</data>
<data name="Command_pal_updatesaves" xml:space="preserve">
<value>Updated all locally cached marker files to latest version.</value>
<comment>Shown after /pal update-saves was successful.</comment>
</data>
<!-- Messages while connecting to the server. These are typically only visible when clicking 'Test connection'. -->
<data name="ConnectionSuccessful" xml:space="preserve">
<value>Connection successful.</value>
</data>
<data name="ConnectionError_NotOnline" xml:space="preserve">
<value>You are not online.</value>
<comment>Shown if you attempt to connect to the server while you have selected 'never upload discoveries, only show traps and coffers i found myself'</comment>
</data>
<data name="ConnectionError_OldVersion" xml:space="preserve">
<value>Your version of Palace Pal is outdated, please update the plugin using the Plugin Installer.</value>
<comment>Shown if the version is too old to create an account or log in.</comment>
</data>
<data name="ConnectionError_CreateAccountFailed" xml:space="preserve">
<value>Could not create account ({0}).</value>
<comment>Creating an account failed with an error code, but there is no (translated) error message for it.</comment>
</data>
<data name="ConnectionError_CreateAccountReturnedNoId" xml:space="preserve">
<value>No account-id after account was attempted to be created.</value>
<comment>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.</comment>
</data>
<data name="ConnectionError_InvalidAccountId" xml:space="preserve">
<value>Invalid account id.</value>
<comment>The account id used was not found on the server.</comment>
</data>
<data name="ConnectionError_LoginFailed" xml:space="preserve">
<value>Could not log in ({0}).</value>
<comment>Logging in failed with an error code, but there is no (translated) error message for it.</comment>
</data>
<data name="ConnectionError_LoginReturnedNoToken" xml:space="preserve">
<value>No login information available.</value>
<comment>The server sent no valid client token, even though the login was successful.</comment>
</data>
<data name="ConnectionError_CouldNotConnectToServer" xml:space="preserve">
<value>Could not connect to server: {0}</value>
</data>
<!-- Config Window -->
<data name="ConfigTab_DeepDungeons" xml:space="preserve">
<value>Deep Dungeons</value>
</data>
<data name="Config_Traps_Show" xml:space="preserve">
<value>Show traps</value>
</data>
<data name="Config_Traps_Color" xml:space="preserve">
<value>Trap color</value>
</data>
<data name="Config_Traps_HideImpossible" xml:space="preserve">
<value>Hide traps not on current floor</value>
<comment>When a trap has no chance of appearing (after a pomander of safety/sight is used), hide it.</comment>
</data>
<data name="Config_Traps_HideImpossible_ToolTip" xml:space="preserve">
<value>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.</value>
</data>
<data name="Config_HoardCoffers_Show" xml:space="preserve">
<value>Show hoard coffers</value>
</data>
<data name="Config_HoardCoffers_Color" xml:space="preserve">
<value>Hoard Coffer color</value>
</data>
<data name="Config_HoardCoffers_HideImpossible" xml:space="preserve">
<value>Hide hoard coffers not on current floor</value>
<comment>When a hoard coffer has no chance of appearing (after a pomander of safety/sight is used), hide it.</comment>
</data>
<data name="Config_HoardCoffers_HideImpossible_ToolTip" xml:space="preserve">
<value>When using a Pomander of intuition, only the actual hoard coffer location is visible, all other (potential) hoard coffers are hidden.</value>
</data>
<data name="Config_SilverCoffer_Show" xml:space="preserve">
<value>Show silver coffers on current floor</value>
</data>
<data name="Config_SilverCoffers_ToolTip" xml:space="preserve">
<value>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.</value>
</data>
<data name="Config_SilverCoffer_Color" xml:space="preserve">
<value>Silver Coffer color</value>
</data>
<data name="Config_SilverCoffer_Filled" xml:space="preserve">
<value>Draw filled</value>
<comment>Whether silver coffers should only be drawn with the circle outline or as filled circle.</comment>
</data>
<data name="ConfigTab_Community" xml:space="preserve">
<value>Community</value>
</data>
<data name="Config_TestConnection" xml:space="preserve">
<value>Test Connection</value>
</data>
<data name="ConfigTab_Import" xml:space="preserve">
<value>Import</value>
</data>
<data name="Config_ImportExplanation1" xml:space="preserve">
<value>Using an export is useful if you're unable to connect to the server, or don't wish to share your findings.</value>
</data>
<data name="Config_ImportExplanation2" xml:space="preserve">
<value>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.</value>
</data>
<data name="Config_ImportExplanation3" xml:space="preserve">
<value>If you aren't offline, importing a file won't have any noticeable effect.</value>
</data>
<data name="Config_ImportDownloadLocation" xml:space="preserve">
<value>Exports are available from {0} (as *.pal files).</value>
</data>
<data name="Config_Import_VisitGitHub" xml:space="preserve">
<value>Visit GitHub</value>
</data>
<data name="Config_SelectImportFile" xml:space="preserve">
<value>File to Import:</value>
</data>
<data name="Config_StartImport" xml:space="preserve">
<value>Start Import</value>
</data>
<data name="Config_UndoImportExplanation1" xml:space="preserve">
<value>Your last import was on {0}, which added the trap/hoard coffer database from {1} created on {2:d}.</value>
</data>
<data name="Config_UndoImportExplanation2" xml:space="preserve">
<value>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).</value>
</data>
<data name="Config_UndoImport" xml:space="preserve">
<value>Undo Import</value>
</data>
<data name="ConfigTab_Export" xml:space="preserve">
<value>Export</value>
</data>
<data name="Config_ExportSource" xml:space="preserve">
<value>Export all markers from {0}:</value>
</data>
<data name="Config_Export_SaveAs" xml:space="preserve">
<value>Save as:</value>
</data>
<data name="Config_StartExport" xml:space="preserve">
<value>Start Export</value>
</data>
<data name="ConfigTab_Renderer" xml:space="preserve">
<value>Renderer</value>
<comment>Configuration tab to select Splatoon or Simple as rendering backend</comment>
</data>
<data name="Config_SelectRenderBackend" xml:space="preserve">
<value>Select which render backend to use for markers:</value>
</data>
<data name="Config_Renderer_Splatoon" xml:space="preserve">
<value>Splatoon</value>
<comment>Splatoon plugin. Do not localize.</comment>
</data>
<data name="Config_Renderer_Splatoon_Hint" xml:space="preserve">
<value>default, required Splatoon to be installed</value>
</data>
<data name="Config_Renderer_Simple" xml:space="preserve">
<value>Simple</value>
</data>
<data name="Config_Renderer_Simple_Hint" xml:space="preserve">
<value>experimental</value>
</data>
<data name="Config_Splatoon_Test" xml:space="preserve">
<value>Splatoon Test:</value>
</data>
<data name="Config_Splatoon_DrawCircles" xml:space="preserve">
<value>Draw trap &amp; coffer circles around self</value>
<comment>To test the Splatoon integration, you can draw markers around yourself.</comment>
</data>
<data name="ConfigTab_Debug" xml:space="preserve">
<value>Debug</value>
</data>
<data name="Config_Debug_NotInADeepDungeon" xml:space="preserve">
<value>You are NOT in a deep dungeon.</value>
</data>
<!-- Statistics Window -->
<data name="Statistics" xml:space="preserve">
<value>Statistics</value>
</data>
<data name="Statistics_TerritoryId" xml:space="preserve">
<value>Id</value>
</data>
<data name="Statistics_InstanceName" xml:space="preserve">
<value>Instance Name</value>
</data>
<data name="Statistics_Traps" xml:space="preserve">
<value>Traps</value>
</data>
<data name="Statistics_HoardCoffers" xml:space="preserve">
<value>Hoard</value>
</data>
<!-- Agreement Window -->
<data name="Explanation_1" xml:space="preserve">
<value>Pal Palace will show where potential trap &amp; hoard coffer locations are.</value>
</data>
<data name="Explanation_2" xml:space="preserve">
<value>To do this, using a pomander to reveal trap or treasure chest locations will save the position of what you see.</value>
</data>
<data name="Explanation_3" xml:space="preserve">
<value>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.</value>
</data>
<data name="Explanation_4" xml:space="preserve">
<value>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.</value>
</data>
<data name="Config_UploadMyDiscoveries_ShowOtherTraps" xml:space="preserve">
<value>Upload my discoveries, show traps &amp; coffers other players have discovered</value>
</data>
<data name="Config_NeverUploadDiscoveries_ShowMyTraps" xml:space="preserve">
<value>Never upload discoveries, show only traps and coffers I found myself</value>
</data>
<data name="Agreement_Warning1" xml:space="preserve">
<value>While this is not an automation feature, you're still very likely to break the ToS.</value>
</data>
<data name="Agreement_Warning2" xml:space="preserve">
<value>Other players in your party can always see where you're standing/walking.</value>
</data>
<data name="Agreement_Warning3" xml:space="preserve">
<value>As such, please avoid mentioning it in-game and do not share videos/screenshots.</value>
</data>
<data name="Agreement_UsingThisOnMyOwnRisk" xml:space="preserve">
<value>I understand I'm using this plugin on my own risk.</value>
</data>
<data name="Agreement_ViewPluginAndServerSourceCode" xml:space="preserve">
<value>View plugin &amp; server source code</value>
</data>
<data name="Agreement_PickOneOption" xml:space="preserve">
<value>Please chose one of the options above.</value>
<comment>Shown if neither of the two radio buttons in the first-time setup window are selected.</comment>
</data>
<!-- Import -->
<data name="ImportCompleteStatistics" xml:space="preserve">
<value>Imported {0} new trap locations and {1} new hoard coffer locations.</value>
<comment>After the import of a *.pal file, the number of traps/hoard coffers is shown as a summary.</comment>
</data>
<data name="Error_ImportFailed" xml:space="preserve">
<value>Import failed: {0}</value>
</data>
<data name="Error_ImportFailed_IncompatibleVersion" xml:space="preserve">
<value>Import failed: Incompatible version.</value>
</data>
<data name="Error_ImportFailed_InvalidFile" xml:space="preserve">
<value>Import failed: Invalid file.</value>
</data>
<!-- Other -->
</root>

View File

@ -113,7 +113,7 @@ namespace Pal.Client.Rendering
public void Draw()
{
if (Color == Plugin.COLOR_INVISIBLE)
if (Color == Plugin.ColorInvisible)
return;
switch (Type)

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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();
}

View File

@ -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<ETerritoryType, TerritoryStatistics> _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))