From ff0c2eed0924850988981c8bdec9cc40a4230bb9 Mon Sep 17 00:00:00 2001 From: JustArchi Date: Sun, 8 Jan 2017 15:09:30 +0100 Subject: [PATCH] Prepare ConfigGenerator for localization --- ArchiSteamFarm/config/ASF.json | 2 +- ConfigGenerator/ASFConfig.cs | 2 + ConfigGenerator/BotConfig.cs | 34 +- ConfigGenerator/ConfigGenerator.csproj | 12 +- ConfigGenerator/EnhancedPropertyGrid.cs | 22 +- ConfigGenerator/GlobalConfig.cs | 89 +++-- ConfigGenerator/JSON/Steam.cs | 2 +- .../Localization/CGStrings.Designer.cs | 364 ++++++++++++++++++ ConfigGenerator/Localization/CGStrings.resx | 238 ++++++++++++ ConfigGenerator/LocalizedCategoryAttribute.cs | 28 ++ ConfigGenerator/Logging.cs | 13 +- ConfigGenerator/MainForm.cs | 28 +- ConfigGenerator/Program.cs | 6 +- ConfigGenerator/Tutorial.cs | 53 +-- 14 files changed, 758 insertions(+), 135 deletions(-) create mode 100644 ConfigGenerator/Localization/CGStrings.Designer.cs create mode 100644 ConfigGenerator/Localization/CGStrings.resx create mode 100644 ConfigGenerator/LocalizedCategoryAttribute.cs diff --git a/ArchiSteamFarm/config/ASF.json b/ArchiSteamFarm/config/ASF.json index f5fac1247..ee2fb77c4 100644 --- a/ArchiSteamFarm/config/ASF.json +++ b/ArchiSteamFarm/config/ASF.json @@ -27,4 +27,4 @@ "UpdateChannel": 1, "WCFHost": "127.0.0.1", "WCFPort": 1242 -} +} \ No newline at end of file diff --git a/ConfigGenerator/ASFConfig.cs b/ConfigGenerator/ASFConfig.cs index 581f6a0d8..fac0247a4 100644 --- a/ConfigGenerator/ASFConfig.cs +++ b/ConfigGenerator/ASFConfig.cs @@ -92,5 +92,7 @@ namespace ConfigGenerator { } } } + + internal virtual void ValidateAndFix() { } } } \ No newline at end of file diff --git a/ConfigGenerator/BotConfig.cs b/ConfigGenerator/BotConfig.cs index 6e5029b65..9e5dda8d8 100644 --- a/ConfigGenerator/BotConfig.cs +++ b/ConfigGenerator/BotConfig.cs @@ -37,14 +37,14 @@ namespace ConfigGenerator { [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] [SuppressMessage("ReSharper", "UnusedMember.Global")] internal sealed class BotConfig : ASFConfig { - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public byte AcceptConfirmationsPeriod { get; set; } = 0; [JsonProperty(Required = Required.DisallowNull)] public bool AcceptGifts { get; set; } = false; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public bool CardDropsRestricted { get; set; } = true; @@ -57,7 +57,7 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public bool DismissInventoryNotifications { get; set; } = true; - [Category("\t\tCore")] + [LocalizedCategory("Core")] [JsonProperty(Required = Required.DisallowNull)] public bool Enabled { get; set; } = false; @@ -70,15 +70,15 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public List GamesPlayedWhileIdle { get; set; } = new List(); - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public bool HandleOfflineMessages { get; set; } = false; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public bool IsBotAccount { get; set; } = false; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace, Required = Required.DisallowNull)] public List LootableTypes { get; set; } = new List { Steam.Item.EType.BoosterPack, @@ -86,15 +86,15 @@ namespace ConfigGenerator { Steam.Item.EType.TradingCard }; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty(Required = Required.DisallowNull)] public ECryptoMethod PasswordFormat { get; set; } = ECryptoMethod.PlainText; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public bool Paused { get; set; } = false; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [Editor(typeof(FlagEnumUiEditor), typeof(UITypeEditor))] [JsonProperty(Required = Required.DisallowNull)] public ERedeemingPreferences RedeemingPreferences { get; set; } = ERedeemingPreferences.None; @@ -108,36 +108,36 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public bool ShutdownOnFarmingFinished { get; set; } = false; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty] public string SteamApiKey { get; set; } = null; - [Category("\t\tCore")] + [LocalizedCategory("Core")] [JsonProperty] public string SteamLogin { get; set; } = null; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty(Required = Required.DisallowNull)] public ulong SteamMasterClanID { get; set; } = 0; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty(Required = Required.DisallowNull)] public ulong SteamMasterID { get; set; } = 0; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty] public string SteamParentalPIN { get; set; } = "0"; - [Category("\t\tCore")] + [LocalizedCategory("Core")] [JsonProperty] [PasswordPropertyText(true)] public string SteamPassword { get; set; } = null; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty] public string SteamTradeToken { get; set; } = null; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [Editor(typeof(FlagEnumUiEditor), typeof(UITypeEditor))] [JsonProperty(Required = Required.DisallowNull)] public ETradingPreferences TradingPreferences { get; set; } = ETradingPreferences.AcceptDonations; diff --git a/ConfigGenerator/ConfigGenerator.csproj b/ConfigGenerator/ConfigGenerator.csproj index 185ab079b..09f97f77b 100644 --- a/ConfigGenerator/ConfigGenerator.csproj +++ b/ConfigGenerator/ConfigGenerator.csproj @@ -74,6 +74,12 @@ Component + + True + True + CGStrings.resx + + Form @@ -83,11 +89,15 @@ - + ConfigPage.cs + + ResXFileCodeGenerator + CGStrings.Designer.cs + MainForm.cs diff --git a/ConfigGenerator/EnhancedPropertyGrid.cs b/ConfigGenerator/EnhancedPropertyGrid.cs index e1149361a..c0cdfdca1 100644 --- a/ConfigGenerator/EnhancedPropertyGrid.cs +++ b/ConfigGenerator/EnhancedPropertyGrid.cs @@ -50,6 +50,7 @@ namespace ConfigGenerator { } base.OnGotFocus(args); + ASFConfig.ValidateAndFix(); ASFConfig.Save(); } @@ -60,28 +61,17 @@ namespace ConfigGenerator { } base.OnPropertyValueChanged(args); + ASFConfig.ValidateAndFix(); ASFConfig.Save(); BotConfig botConfig = ASFConfig as BotConfig; - if (botConfig != null) { - if (!botConfig.Enabled) { - return; - } - - Tutorial.OnAction(Tutorial.EPhase.BotEnabled); - if (!string.IsNullOrEmpty(botConfig.SteamLogin) && !string.IsNullOrEmpty(botConfig.SteamPassword)) { - Tutorial.OnAction(Tutorial.EPhase.BotReady); - } + if (botConfig?.Enabled != true) { return; } - GlobalConfig globalConfig = ASFConfig as GlobalConfig; - if (globalConfig == null) { - return; - } - - if (globalConfig.SteamOwnerID != 0) { - Tutorial.OnAction(Tutorial.EPhase.GlobalConfigReady); + Tutorial.OnAction(Tutorial.EPhase.BotEnabled); + if (!string.IsNullOrEmpty(botConfig.SteamLogin) && !string.IsNullOrEmpty(botConfig.SteamPassword)) { + Tutorial.OnAction(Tutorial.EPhase.BotReady); } } } diff --git a/ConfigGenerator/GlobalConfig.cs b/ConfigGenerator/GlobalConfig.cs index 1821e8fb2..7b8f8f7be 100644 --- a/ConfigGenerator/GlobalConfig.cs +++ b/ConfigGenerator/GlobalConfig.cs @@ -24,10 +24,10 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net.Sockets; +using ConfigGenerator.Localization; using Newtonsoft.Json; namespace ConfigGenerator { @@ -45,11 +45,11 @@ namespace ConfigGenerator { // This is hardcoded blacklist which should not be possible to change private static readonly HashSet GlobalBlacklist = new HashSet { 267420, 303700, 335590, 368020, 425280, 480730, 566020 }; - [Category("\tUpdates")] + [LocalizedCategory("Updates")] [JsonProperty(Required = Required.DisallowNull)] public bool AutoRestart { get; set; } = true; - [Category("\tUpdates")] + [LocalizedCategory("Updates")] [JsonProperty(Required = Required.DisallowNull)] public bool AutoUpdates { get; set; } = true; @@ -59,39 +59,39 @@ namespace ConfigGenerator { [JsonProperty] public string CurrentCulture { get; set; } = null; - [Category("\tDebugging")] + [LocalizedCategory("Debugging")] [JsonProperty(Required = Required.DisallowNull)] public bool Debug { get; set; } = false; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte FarmingDelay { get; set; } = DefaultFarmingDelay; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte GiftsLimiterDelay { get; set; } = 1; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public bool Headless { get; set; } = false; - [Category("\tDebugging")] + [LocalizedCategory("Debugging")] [JsonProperty(Required = Required.DisallowNull)] public byte HttpTimeout { get; set; } = DefaultHttpTimeout; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte IdleFarmingPeriod { get; set; } = 3; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte InventoryLimiterDelay { get; set; } = 3; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte LoginLimiterDelay { get; set; } = 10; - [Category("\tPerformance")] + [LocalizedCategory("Performance")] [JsonProperty(Required = Required.DisallowNull)] public byte MaxFarmingTime { get; set; } = DefaultMaxFarmingTime; @@ -101,23 +101,23 @@ namespace ConfigGenerator { [JsonProperty(Required = Required.DisallowNull)] public bool Statistics { get; set; } = true; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty(Required = Required.DisallowNull)] public ulong SteamOwnerID { get; set; } = 0; - [Category("\tAdvanced")] + [LocalizedCategory("Advanced")] [JsonProperty(Required = Required.DisallowNull)] public ProtocolType SteamProtocol { get; set; } = DefaultSteamProtocol; - [Category("\tUpdates")] + [LocalizedCategory("Updates")] [JsonProperty(Required = Required.DisallowNull)] public EUpdateChannel UpdateChannel { get; set; } = EUpdateChannel.Stable; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty] public string WCFHost { get; set; } = "127.0.0.1"; - [Category("\tAccess")] + [LocalizedCategory("Access")] [JsonProperty(Required = Required.DisallowNull)] public ushort WCFPort { get; set; } = DefaultWCFPort; @@ -156,44 +156,55 @@ namespace ConfigGenerator { } globalConfig.FilePath = filePath; + globalConfig.ValidateAndFix(); + return globalConfig; + } - // SK2 supports only TCP and UDP steam protocols - // Ensure that user can't screw this up - switch (globalConfig.SteamProtocol) { + internal override void ValidateAndFix() { + base.ValidateAndFix(); + + switch (SteamProtocol) { case ProtocolType.Tcp: case ProtocolType.Udp: break; default: - Logging.LogGenericWarning("Configured SteamProtocol is invalid: " + globalConfig.SteamProtocol + ". Value of " + DefaultSteamProtocol + " will be used instead"); - globalConfig.SteamProtocol = DefaultSteamProtocol; + Logging.LogGenericWarning(string.Format(CGStrings.ErrorConfigPropertyInvalid, nameof(SteamProtocol), SteamProtocol)); + SteamProtocol = DefaultSteamProtocol; + Save(); + Logging.LogGenericWarning(string.Format(CGStrings.WarningConfigPropertyModified, nameof(SteamProtocol), SteamProtocol)); break; } - // User might not know what he's doing - // Ensure that he can't screw core ASF variables - if (globalConfig.MaxFarmingTime == 0) { - Logging.LogGenericWarning("Configured MaxFarmingTime is invalid: " + globalConfig.MaxFarmingTime + ". Value of " + DefaultMaxFarmingTime + " will be used instead"); - globalConfig.MaxFarmingTime = DefaultMaxFarmingTime; + if (MaxFarmingTime == 0) { + Logging.LogGenericWarning(string.Format(CGStrings.ErrorConfigPropertyInvalid, nameof(MaxFarmingTime), MaxFarmingTime)); + MaxFarmingTime = DefaultMaxFarmingTime; + Save(); + Logging.LogGenericWarning(string.Format(CGStrings.WarningConfigPropertyModified, nameof(MaxFarmingTime), MaxFarmingTime)); + } - if (globalConfig.FarmingDelay == 0) { - Logging.LogGenericWarning("Configured FarmingDelay is invalid: " + globalConfig.FarmingDelay + ". Value of " + DefaultFarmingDelay + " will be used instead"); - globalConfig.FarmingDelay = DefaultFarmingDelay; + if (FarmingDelay == 0) { + Logging.LogGenericWarning(string.Format(CGStrings.ErrorConfigPropertyInvalid, nameof(FarmingDelay), FarmingDelay)); + FarmingDelay = DefaultFarmingDelay; + Save(); + Logging.LogGenericWarning(string.Format(CGStrings.WarningConfigPropertyModified, nameof(FarmingDelay), FarmingDelay)); } - if (globalConfig.HttpTimeout == 0) { - Logging.LogGenericWarning("Configured HttpTimeout is invalid: " + globalConfig.HttpTimeout + ". Value of " + DefaultHttpTimeout + " will be used instead"); - globalConfig.HttpTimeout = DefaultHttpTimeout; + if (HttpTimeout == 0) { + Logging.LogGenericWarning(string.Format(CGStrings.ErrorConfigPropertyInvalid, nameof(HttpTimeout), HttpTimeout)); + HttpTimeout = DefaultHttpTimeout; + Save(); + Logging.LogGenericWarning(string.Format(CGStrings.WarningConfigPropertyModified, nameof(HttpTimeout), HttpTimeout)); } - if (globalConfig.WCFPort != 0) { - return globalConfig; + if (WCFPort != 0) { + return; } - Logging.LogGenericWarning("Configured WCFPort is invalid: " + globalConfig.WCFPort + ". Value of " + DefaultWCFPort + " will be used instead"); - globalConfig.WCFPort = DefaultWCFPort; - - return globalConfig; + Logging.LogGenericWarning(string.Format(CGStrings.ErrorConfigPropertyInvalid, nameof(WCFPort), WCFPort)); + WCFPort = DefaultWCFPort; + Save(); + Logging.LogGenericWarning(string.Format(CGStrings.WarningConfigPropertyModified, nameof(WCFPort), WCFPort)); } internal enum EUpdateChannel : byte { diff --git a/ConfigGenerator/JSON/Steam.cs b/ConfigGenerator/JSON/Steam.cs index f3a224e8b..5cf865dc2 100644 --- a/ConfigGenerator/JSON/Steam.cs +++ b/ConfigGenerator/JSON/Steam.cs @@ -39,4 +39,4 @@ namespace ConfigGenerator.JSON { } } } -} +} \ No newline at end of file diff --git a/ConfigGenerator/Localization/CGStrings.Designer.cs b/ConfigGenerator/Localization/CGStrings.Designer.cs new file mode 100644 index 000000000..22011493a --- /dev/null +++ b/ConfigGenerator/Localization/CGStrings.Designer.cs @@ -0,0 +1,364 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ConfigGenerator.Localization { + 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 CGStrings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal CGStrings() { + } + + /// + /// 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("ConfigGenerator.Localization.CGStrings", typeof(CGStrings).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 Access. + /// + internal static string CategoryAccess { + get { + return ResourceManager.GetString("CategoryAccess", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Advanced. + /// + internal static string CategoryAdvanced { + get { + return ResourceManager.GetString("CategoryAdvanced", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Core. + /// + internal static string CategoryCore { + get { + return ResourceManager.GetString("CategoryCore", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Debugging. + /// + internal static string CategoryDebugging { + get { + return ResourceManager.GetString("CategoryDebugging", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Performance. + /// + internal static string CategoryPerformance { + get { + return ResourceManager.GetString("CategoryPerformance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Updates. + /// + internal static string CategoryUpdates { + get { + return ResourceManager.GetString("CategoryUpdates", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Do you really want to remove this config?. + /// + internal static string ConfirmRemoval { + get { + return ResourceManager.GetString("ConfirmRemoval", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your bot name is empty!. + /// + internal static string ErrorBotNameEmpty { + get { + return ResourceManager.GetString("ErrorBotNameEmpty", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't remove global config!. + /// + internal static string ErrorCantRemoveGlobalConfig { + get { + return ResourceManager.GetString("ErrorCantRemoveGlobalConfig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You can't rename global config!. + /// + internal static string ErrorCantRenameGlobalConfig { + get { + return ResourceManager.GetString("ErrorCantRenameGlobalConfig", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Config directory could not be found!. + /// + internal static string ErrorConfigDirectoryNotFound { + get { + return ResourceManager.GetString("ErrorConfigDirectoryNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Configured {0} property is invalid: {1}. + /// + internal static string ErrorConfigPropertyInvalid { + get { + return ResourceManager.GetString("ErrorConfigPropertyInvalid", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This name is already used!. + /// + internal static string ErrorNameAlreadyUsed { + get { + return ResourceManager.GetString("ErrorNameAlreadyUsed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This name is reserved!. + /// + internal static string ErrorNameReserved { + get { + return ResourceManager.GetString("ErrorNameReserved", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} is null!. + /// + internal static string ErrorObjectIsNull { + get { + return ResourceManager.GetString("ErrorObjectIsNull", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You've attempted to use invalid ConfigGenerator version for your ASF! + /// + ///ASF: {0} | ConfigGenerator: {1} + /// + ///Please use matching ConfigGenerator version for your ASF binary. You'll be redirected to appropriate release.... + /// + internal static string ErrorVersionMismatch { + get { + return ResourceManager.GetString("ErrorVersionMismatch", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New. + /// + internal static string New { + get { + return ResourceManager.GetString("New", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Removal. + /// + internal static string Removal { + get { + return ResourceManager.GetString("Removal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rename. + /// + internal static string Rename { + get { + return ResourceManager.GetString("Rename", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Excellent! Now your bot instance is enabled. In fact, that was everything you had to do in order to use this bot in ASF, but you might want to configure at least 2 more config properties: {0} and {1}. If you want to continue the tutorial, please do so. Remember to refer to the wiki if you're unsure how given property should be configured, or if you need additional help.. + /// + internal static string TutorialBotFormEnabled { + get { + return ResourceManager.GetString("TutorialBotFormEnabled", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Your ASF is now ready! Simply launch ASF.exe binary and if you typed everything properly, you should notice that ASF is logging in and starts idling. If you have SteamGuard or two-factor authentication enabled, ASF might need to ask you for those credentials during runtime.. + /// + internal static string TutorialBotFormReady { + get { + return ResourceManager.GetString("TutorialBotFormReady", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Congratulations! You've done everything that is needed in order to make ASF usable, that also finishes the tutorial that we prepared for you. It's highly recommended to read entire configuraton section on the wiki now, as ASF offers some really neat features for you to configure, such as offline farming or tuning ASF for using the most efficient idling algorithm for your account. All of that is optional though, and you're free to close our configurator whenever you wish. We hope that you'll enjoy the softwa [rest of string was truncated]";. + /// + internal static string TutorialFinished { + get { + return ResourceManager.GetString("TutorialFinished", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to At the top of the window you can notice currently loaded configs, and 3 extra buttons for removing [-], renaming [~] and adding new ones [+].. + /// + internal static string TutorialMainFormBotsManagementButtons { + get { + return ResourceManager.GetString("TutorialMainFormBotsManagementButtons", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please note that all information about available config properties, including their description, purpose, and accepted values, is available on our GitHub wiki. Please use it as a reference.. + /// + internal static string TutorialMainFormConfigurationWiki { + get { + return ResourceManager.GetString("TutorialMainFormConfigurationWiki", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In the middle of the window you can configure all config properties that are available for you, for your currently selected config.. + /// + internal static string TutorialMainFormConfigurationWindow { + get { + return ResourceManager.GetString("TutorialMainFormConfigurationWindow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Alright, let's start configuring our ASF. Click on the plus [+] button in order to add your first steam account!. + /// + internal static string TutorialMainFormFinished { + get { + return ResourceManager.GetString("TutorialMainFormFinished", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to In the top right corner you can find help button [?] which will redirect you to ASF wiki for more information.. + /// + internal static string TutorialMainFormHelpButton { + get { + return ResourceManager.GetString("TutorialMainFormHelpButton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This is the main ASF ConfigGenerator screen, it's really easy to use!. + /// + internal static string TutorialMainFormShown { + get { + return ResourceManager.GetString("TutorialMainFormShown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to As you can see, your bot is now ready to be configured! First thing that you want to do is switching {0} property from false to true, try it!. + /// + internal static string TutorialNewBotFormFinished { + get { + return ResourceManager.GetString("TutorialNewBotFormFinished", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Good job! You'll be asked for your bot name now. A good example would be a nickname that you're using for the steam account you're about to configure, or any other name of your choice which will be easy for you to connect with the bot instance that is being configured.. + /// + internal static string TutorialNewBotFormShown { + get { + return ResourceManager.GetString("TutorialNewBotFormShown", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Welcome! I noticed that you're using ASF ConfigGenerator for the first time, so let me help you a bit.. + /// + internal static string TutorialStart { + get { + return ResourceManager.GetString("TutorialStart", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Please enter new bot name: . + /// + internal static string UserInputBotName { + get { + return ResourceManager.GetString("UserInputBotName", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} has been set to: {1}. + /// + internal static string WarningConfigPropertyModified { + get { + return ResourceManager.GetString("WarningConfigPropertyModified", resourceCulture); + } + } + } +} diff --git a/ConfigGenerator/Localization/CGStrings.resx b/ConfigGenerator/Localization/CGStrings.resx new file mode 100644 index 000000000..547a0a89f --- /dev/null +++ b/ConfigGenerator/Localization/CGStrings.resx @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Access + + + Advanced + + + Core + + + Debugging + + + Performance + + + Updates + + + Do you really want to remove this config? + + + Your bot name is empty! + + + You can't remove global config! + + + You can't rename global config! + + + Config directory could not be found! + + + Configured {0} property is invalid: {1} + {0} will be replaced by name of the configuration property, {1} will be replaced by invalid value + + + This name is already used! + This happens e.g. when user wants to create a bot with name that exists already + + + This name is reserved! + This happens e.g. when user wants to create a bot with reserved name, such as "ASF" + + + {0} is null! + {0} will be replaced by object's name + + + You've attempted to use invalid ConfigGenerator version for your ASF! + +ASF: {0} | ConfigGenerator: {1} + +Please use matching ConfigGenerator version for your ASF binary. You'll be redirected to appropriate release... + {0} will be replaced by ASF version (string), {1} will be replaced by ConfigGenerator version (string). Please note that this string should include newlines for formatting. + + + New + This is used as MessageBox title + + + Removal + This is used as MessageBox title + + + Rename + This is used as MessageBox title + + + Excellent! Now your bot instance is enabled. In fact, that was everything you had to do in order to use this bot in ASF, but you might want to configure at least 2 more config properties: {0} and {1}. If you want to continue the tutorial, please do so. Remember to refer to the wiki if you're unsure how given property should be configured, or if you need additional help. + {0} will be replaced by "SteamLogin" configuration property, {1} will be replaced by "SteamPassword" configuration property + + + Your ASF is now ready! Simply launch ASF.exe binary and if you typed everything properly, you should notice that ASF is logging in and starts idling. If you have SteamGuard or two-factor authentication enabled, ASF might need to ask you for those credentials during runtime. + + + Congratulations! You've done everything that is needed in order to make ASF usable, that also finishes the tutorial that we prepared for you. It's highly recommended to read entire configuraton section on the wiki now, as ASF offers some really neat features for you to configure, such as offline farming or tuning ASF for using the most efficient idling algorithm for your account. All of that is optional though, and you're free to close our configurator whenever you wish. We hope that you'll enjoy the software that we coded for you! + + + At the top of the window you can notice currently loaded configs, and 3 extra buttons for removing [-], renaming [~] and adding new ones [+]. + If possible, try to keep visual representation of buttons: [-], [~] and [+] + + + Please note that all information about available config properties, including their description, purpose, and accepted values, is available on our GitHub wiki. Please use it as a reference. + {0} will be replaced by URL to our wiki + + + In the middle of the window you can configure all config properties that are available for you, for your currently selected config. + + + Alright, let's start configuring our ASF. Click on the plus [+] button in order to add your first steam account! + + + In the top right corner you can find help button [?] which will redirect you to ASF wiki for more information. + If possible, try to keep visual representation of [?] button + + + This is the main ASF ConfigGenerator screen, it's really easy to use! + + + As you can see, your bot is now ready to be configured! First thing that you want to do is switching {0} property from false to true, try it! + {0} will be replaced by name of the configuration property ("Enabled") + + + Good job! You'll be asked for your bot name now. A good example would be a nickname that you're using for the steam account you're about to configure, or any other name of your choice which will be easy for you to connect with the bot instance that is being configured. + + + Welcome! I noticed that you're using ASF ConfigGenerator for the first time, so let me help you a bit. + + + Please enter new bot name: + Please note that this translation should end with space + + + {0} has been set to: {1} + {0} will be replaced by name of the configuration property, {1} will be replaced by new value + + \ No newline at end of file diff --git a/ConfigGenerator/LocalizedCategoryAttribute.cs b/ConfigGenerator/LocalizedCategoryAttribute.cs new file mode 100644 index 000000000..2952ce126 --- /dev/null +++ b/ConfigGenerator/LocalizedCategoryAttribute.cs @@ -0,0 +1,28 @@ +using System.ComponentModel; +using ConfigGenerator.Localization; + +namespace ConfigGenerator { + internal sealed class LocalizedCategoryAttribute : CategoryAttribute { + internal LocalizedCategoryAttribute(string key) : base(key) { } + + protected override string GetLocalizedString(string value) { + switch (value) { + case "Access": + return CGStrings.CategoryAccess; + case "Advanced": + return CGStrings.CategoryAdvanced; + case "Core": + return '\t' + CGStrings.CategoryCore; + case "Debugging": + return CGStrings.CategoryDebugging; + case "Performance": + return CGStrings.CategoryPerformance; + case "Updates": + return CGStrings.CategoryUpdates; + default: + Logging.LogGenericWarning("Unknown value: " + value); + return value; + } + } + } +} diff --git a/ConfigGenerator/Logging.cs b/ConfigGenerator/Logging.cs index b247e164f..8296fd4de 100644 --- a/ConfigGenerator/Logging.cs +++ b/ConfigGenerator/Logging.cs @@ -26,6 +26,7 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Windows.Forms; +using ConfigGenerator.Localization; using ConfigGenerator.Properties; namespace ConfigGenerator { @@ -77,15 +78,11 @@ namespace ConfigGenerator { [SuppressMessage("ReSharper", "ExplicitCallerInfoArgument")] internal static void LogNullError(string nullObjectName, [CallerMemberName] string previousMethodName = null) { - while (true) { - if (string.IsNullOrEmpty(nullObjectName)) { - nullObjectName = nameof(nullObjectName); - continue; - } - - LogGenericError(nullObjectName + " is null!", previousMethodName); - break; + if (string.IsNullOrEmpty(nullObjectName)) { + return; } + + LogGenericError(string.Format(CGStrings.ErrorObjectIsNull, nullObjectName), previousMethodName); } private static void LogGenericError(string message, [CallerMemberName] string previousMethodName = null) { diff --git a/ConfigGenerator/MainForm.cs b/ConfigGenerator/MainForm.cs index 624725a5c..5dbbf2157 100644 --- a/ConfigGenerator/MainForm.cs +++ b/ConfigGenerator/MainForm.cs @@ -30,9 +30,11 @@ using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; using ArchiSteamFarm; +using ConfigGenerator.Localization; namespace ConfigGenerator { internal sealed partial class MainForm : Form { + private const string GitHubWikiConfigurationURL = "https://github.com/" + SharedInfo.GithubRepo + "/wiki/Configuration"; private const byte ReservedTabs = 3; private readonly TabPage NewTab = new TabPage { Text = @"+" }; @@ -53,9 +55,7 @@ namespace ConfigGenerator { } args.Cancel = true; - Tutorial.OnAction(Tutorial.EPhase.Help); - Process.Start("https://github.com/" + SharedInfo.GithubRepo + "/wiki/Configuration"); - Tutorial.OnAction(Tutorial.EPhase.HelpFinished); + Process.Start(GitHubWikiConfigurationURL); } private void MainForm_Load(object sender, EventArgs args) { @@ -118,13 +118,13 @@ namespace ConfigGenerator { if (configPage == ASFTab) { MainTab.SelectedTab = ASFTab; - Logging.LogGenericErrorWithoutStacktrace("You can't remove global config!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorCantRemoveGlobalConfig); return; } MainTab.SelectedTab = configPage; - if (DialogBox.YesNoBox("Removal", "Do you really want to remove this config?") != DialogResult.Yes) { + if (DialogBox.YesNoBox(CGStrings.Removal, CGStrings.ConfirmRemoval) != DialogResult.Yes) { return; } @@ -140,19 +140,19 @@ namespace ConfigGenerator { if (configPage == ASFTab) { MainTab.SelectedTab = ASFTab; - Logging.LogGenericErrorWithoutStacktrace("You can't rename global config!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorCantRenameGlobalConfig); return; } MainTab.SelectedTab = configPage; string input; - if (DialogBox.InputBox("Rename", "Your new bot name:", out input) != DialogResult.OK) { + if (DialogBox.InputBox(CGStrings.Rename, CGStrings.UserInputBotName, out input) != DialogResult.OK) { return; } if (string.IsNullOrEmpty(input)) { - Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorBotNameEmpty); return; } @@ -173,12 +173,12 @@ namespace ConfigGenerator { Tutorial.OnAction(Tutorial.EPhase.BotNickname); string input; - if (DialogBox.InputBox("New", "Your new bot name:", out input) != DialogResult.OK) { + if (DialogBox.InputBox(CGStrings.New, CGStrings.UserInputBotName, out input) != DialogResult.OK) { return; } if (string.IsNullOrEmpty(input)) { - Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorBotNameEmpty); return; } @@ -186,7 +186,7 @@ namespace ConfigGenerator { input = Regex.Replace(input, @"\s+", ""); if (string.IsNullOrEmpty(input)) { - Logging.LogGenericErrorWithoutStacktrace("Your bot name is empty!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorBotNameEmpty); return; } @@ -194,12 +194,12 @@ namespace ConfigGenerator { case SharedInfo.ASF: case "example": case "minimal": - Logging.LogGenericErrorWithoutStacktrace("This name is reserved!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorNameReserved); return; } if (ASFConfig.ASFConfigs.Select(config => Path.GetFileNameWithoutExtension(config.FilePath)).Any(fileNameWithoutExtension => (fileNameWithoutExtension == null) || fileNameWithoutExtension.Equals(input))) { - Logging.LogGenericErrorWithoutStacktrace("Bot with such name exists already!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorNameAlreadyUsed); return; } @@ -209,8 +209,6 @@ namespace ConfigGenerator { MainTab.TabPages.Insert(MainTab.TabPages.Count - ReservedTabs, newConfigPage); MainTab.SelectedTab = newConfigPage; Tutorial.OnAction(Tutorial.EPhase.BotNicknameFinished); - } else if (args.TabPage == ASFTab) { - Tutorial.OnAction(Tutorial.EPhase.GlobalConfigOpened); } } } diff --git a/ConfigGenerator/Program.cs b/ConfigGenerator/Program.cs index f158afc88..f0b90c7e8 100644 --- a/ConfigGenerator/Program.cs +++ b/ConfigGenerator/Program.cs @@ -29,6 +29,7 @@ using System.Reflection; using System.Threading.Tasks; using System.Windows.Forms; using ArchiSteamFarm; +using ConfigGenerator.Localization; namespace ConfigGenerator { internal static class Program { @@ -63,7 +64,7 @@ namespace ConfigGenerator { } if (!Directory.Exists(SharedInfo.ConfigDirectory)) { - Logging.LogGenericErrorWithoutStacktrace("Config directory could not be found!"); + Logging.LogGenericErrorWithoutStacktrace(CGStrings.ErrorConfigDirectoryNotFound); Environment.Exit(1); } @@ -80,8 +81,7 @@ namespace ConfigGenerator { return; } - Logging.LogGenericErrorWithoutStacktrace("Version of ASF and ConfigGenerator doesn't match!" + Environment.NewLine + "ASF version: " + asfVersion + " | ConfigGenerator version: " + cgVersion + Environment.NewLine + Environment.NewLine + "Please use ConfigGenerator from the same ASF release, I'll redirect you to appropriate ASF release..."); - + Logging.LogGenericErrorWithoutStacktrace(string.Format(CGStrings.ErrorVersionMismatch, asfVersion, cgVersion)); Process.Start("https://github.com/" + SharedInfo.GithubRepo + "/releases/tag/" + asfVersion); Environment.Exit(1); } diff --git a/ConfigGenerator/Tutorial.cs b/ConfigGenerator/Tutorial.cs index 00b23f2f7..51a92848d 100644 --- a/ConfigGenerator/Tutorial.cs +++ b/ConfigGenerator/Tutorial.cs @@ -22,6 +22,8 @@ */ +using ConfigGenerator.Localization; + namespace ConfigGenerator { internal static class Tutorial { internal static bool Enabled { private get; set; } = true; @@ -35,50 +37,36 @@ namespace ConfigGenerator { switch (phase) { case EPhase.Unknown: + case EPhase.Finished: break; case EPhase.Start: - Logging.LogGenericInfoWithoutStacktrace("Hello there! I noticed that you're using ASF Config Generator for the first time, so let me help you a bit."); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialStart); break; case EPhase.Shown: - Logging.LogGenericInfoWithoutStacktrace("You can now notice the main ASF Config Generator screen, it's really easy to use!"); - Logging.LogGenericInfoWithoutStacktrace("At the top of the window you can notice currently loaded configs, and 3 extra buttons for removing, renaming and adding new ones."); - Logging.LogGenericInfoWithoutStacktrace("In the middle of the window you will be able to configure all config properties that are available for you."); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormShown); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormBotsManagementButtons); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormConfigurationWindow); + if (!Runtime.IsRunningOnMono) { - Logging.LogGenericInfoWithoutStacktrace("In the top right corner you can find help button [?] which will redirect you to ASF wiki where you can find more information."); - Logging.LogGenericInfoWithoutStacktrace("Please click the help button to continue."); - } else { - Logging.LogGenericInfoWithoutStacktrace("Please visit ASF wiki if you're in doubt - you can find more information there."); - Logging.LogGenericInfoWithoutStacktrace("Alright, let's start configuring our ASF. Click on the plus [+] button to add your first steam account to ASF!"); - NextPhase = EPhase.HelpFinished; + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormHelpButton); } - break; - case EPhase.Help: - Logging.LogGenericInfoWithoutStacktrace("Well done! On ASF wiki you can find detailed help about every config property you're going to configure in a moment."); - break; - case EPhase.HelpFinished: - Logging.LogGenericInfoWithoutStacktrace("Alright, let's start configuring our ASF. Click on the plus [+] button to add your first steam account to ASF!"); + + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormConfigurationWiki); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialMainFormFinished); + break; case EPhase.BotNickname: - Logging.LogGenericInfoWithoutStacktrace("Good job! You'll be asked for your bot name now. A good example would be a nickname that you're using for the steam account you're configuring right now, or any other name of your choice which will be easy for you to connect with bot instance that is being configured. Please don't use spaces in the name."); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialNewBotFormShown); break; case EPhase.BotNicknameFinished: - Logging.LogGenericInfoWithoutStacktrace("As you can see your bot config is now ready to configure!"); - Logging.LogGenericInfoWithoutStacktrace("First thing that you want to do is switching \"Enabled\" property from False to True, try it!"); + Logging.LogGenericInfoWithoutStacktrace(string.Format(CGStrings.TutorialNewBotFormFinished, nameof(BotConfig.Enabled))); break; case EPhase.BotEnabled: - Logging.LogGenericInfoWithoutStacktrace("Excellent! Now your bot instance is enabled. You need to configure at least 2 more config properties - \"SteamLogin\" and \"SteamPassword\". The tutorial will continue after you're done with it. Remember to visit ASF wiki by clicking the help icon if you're unsure how given property should be configured!"); + Logging.LogGenericInfoWithoutStacktrace(string.Format(CGStrings.TutorialBotFormEnabled, nameof(BotConfig.SteamLogin), nameof(BotConfig.SteamPassword))); break; case EPhase.BotReady: - Logging.LogGenericInfoWithoutStacktrace("If the data you put is proper, then your bot is ready to run! We need to do only one more thing now. Visit global ASF config, which is labelled as \"ASF\" on your config tab."); - break; - case EPhase.GlobalConfigOpened: - Logging.LogGenericInfoWithoutStacktrace("While bot config affects only given bot instance you're configuring, global config affects whole ASF process, including all configured bots."); - Logging.LogGenericInfoWithoutStacktrace("In order to fully configure your ASF, I suggest to fill \"SteamOwnerID\" property. Remember, if you don't know what to put, help button is always there for you!"); - break; - case EPhase.GlobalConfigReady: - Logging.LogGenericInfoWithoutStacktrace("Your ASF is now ready! Simply launch ASF process by double-clicking ASF.exe binary and if you did everything properly, you should now notice that ASF logs in on your account and starts farming. If you have SteamGuard or 2FA authorization enabled, ASF will ask you for that once"); - Logging.LogGenericInfoWithoutStacktrace("Congratulations! You've done everything that is needed in order to make ASF \"work\". I highly recommend reading the wiki now, as ASF offers some really neat features for you to configure, such as offline farming or deciding upon most efficient cards farming algorithm."); - Logging.LogGenericInfoWithoutStacktrace("If you'd like to add another steam account for farming, simply click the plus [+] button and add another instance. You can also rename bots [~] and remove them [-]. Good luck!"); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialBotFormReady); + Logging.LogGenericInfoWithoutStacktrace(CGStrings.TutorialFinished); Enabled = false; break; } @@ -90,14 +78,11 @@ namespace ConfigGenerator { Unknown, Start, Shown, - Help, - HelpFinished, BotNickname, BotNicknameFinished, BotEnabled, BotReady, - GlobalConfigOpened, - GlobalConfigReady + Finished } } } \ No newline at end of file