diff --git a/docs-website/docs/admin-panel/configuration-captions.md b/docs-website/docs/admin-panel/configuration-captions.md index 5f97a1f6c..70f39988e 100644 --- a/docs-website/docs/admin-panel/configuration-captions.md +++ b/docs-website/docs/admin-panel/configuration-captions.md @@ -161,3 +161,29 @@ editors, a translated hint appears below the original name or description. The input still edits the stored English text, which configuration updates use to identify attributes. Unknown or customized text is shown unchanged. These display translations do not require linking or applying configuration names. + +## Cash shop package names + +The cash shop catalog uses localized package names, including the list, search and +name editor. Searches accept both the displayed translation and the neutral name. +New Season 6 configurations include the resource links. For an existing catalog, +link the names and review and apply the translations on this page, then restart +as described above. Linking uses the package number from the client script and +requires an exact match of the neutral name. Customized names and ambiguous +package numbers are not automatically linked. + +This changes admin panel captions only. The client still displays its own shop +script. Package and product numbers, prices, delivery items and sale flags are +unchanged. Names remain stored in the same database text column; the localized +string converter also reads existing plain English values. + +Chinese names reuse the existing item translations where applicable. The +[official legacy item guide](https://mu.zhaouc.com/01_news/updatecn/s5/s5_4.htm) +confirms the unicorn, skeleton pet, transformation ring and AG/SD aura names. +[Official VIP rewards](https://mu.zhaouc.com/event/vipxt/vip/) also document potion, +seal and scroll terminology. English-client promotions such as eX700 celebration +packages, gold-channel packages, charms, statues and rare-item tickets use +provisional descriptive translations; they are not presented as verified Chinese +Season 6 client labels. Other labels without a confirmed Season 6 counterpart +also remain descriptive translations. Brackets, GP markers, durations and bundle +quantities are preserved to distinguish the script's offers. diff --git a/src/DataModel/Configuration/CashShopPackage.cs b/src/DataModel/Configuration/CashShopPackage.cs index 5ab82ce11..2f5d0c4e6 100644 --- a/src/DataModel/Configuration/CashShopPackage.cs +++ b/src/DataModel/Configuration/CashShopPackage.cs @@ -26,7 +26,7 @@ public partial class CashShopPackage /// Gets or sets the name, which is only shown in the admin panel. /// The client shows the name of its script. /// - public string Name { get; set; } = string.Empty; + public LocalizedString Name { get; set; } = new(string.Empty); /// /// Gets or sets the price of a bundle package. @@ -69,6 +69,6 @@ public partial class CashShopPackage /// public override string ToString() { - return $"{this.PackageSequence}: {this.Name}"; + return $"{this.PackageSequence}: {this.Name.GetTranslation(System.Globalization.CultureInfo.CurrentUICulture)}"; } } diff --git a/src/Persistence/EntityFramework/CompiledModels/EntityDataContext/CashShopPackageEntityType.cs b/src/Persistence/EntityFramework/CompiledModels/EntityDataContext/CashShopPackageEntityType.cs index cf208d31b..557d6bd93 100644 --- a/src/Persistence/EntityFramework/CompiledModels/EntityDataContext/CashShopPackageEntityType.cs +++ b/src/Persistence/EntityFramework/CompiledModels/EntityDataContext/CashShopPackageEntityType.cs @@ -3,10 +3,12 @@ using System.Collections.Generic; using System.Reflection; using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.Interfaces; using MUnique.OpenMU.Persistence.EntityFramework.Model; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; #pragma warning disable 219, 612, 618 @@ -80,9 +82,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas var name = runtimeEntityType.AddProperty( "Name", - typeof(string), + typeof(MUnique.OpenMU.Interfaces.LocalizedString), propertyInfo: typeof(MUnique.OpenMU.DataModel.Configuration.CashShopPackage).GetProperty("Name", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), fieldInfo: typeof(MUnique.OpenMU.DataModel.Configuration.CashShopPackage).GetField("k__BackingField", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)); + name.SetValueConverter(new ValueConverter( + string (LocalizedString value) => value.Value ?? string.Empty, + LocalizedString (string value) => new LocalizedString(value))); + name.SetSentinelFromProviderValue(""); name.AddAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.None); var packageSequence = runtimeEntityType.AddProperty( diff --git a/src/Persistence/EntityFramework/EntityDataContext.cs b/src/Persistence/EntityFramework/EntityDataContext.cs index 7d2e2c599..1054c5ec1 100644 --- a/src/Persistence/EntityFramework/EntityDataContext.cs +++ b/src/Persistence/EntityFramework/EntityDataContext.cs @@ -129,6 +129,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); + modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); modelBuilder.Entity().Apply(); diff --git a/src/Persistence/EntityFramework/Extensions/ModelBuilder/CashShopExtensions.cs b/src/Persistence/EntityFramework/Extensions/ModelBuilder/CashShopExtensions.cs index 25b0517c3..39f4ed50c 100644 --- a/src/Persistence/EntityFramework/Extensions/ModelBuilder/CashShopExtensions.cs +++ b/src/Persistence/EntityFramework/Extensions/ModelBuilder/CashShopExtensions.cs @@ -13,6 +13,15 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Extensions.ModelBuilder; /// internal static class CashShopExtensions { + /// + /// Applies the settings for the entity. + /// + /// The builder. + public static void Apply(this EntityTypeBuilder builder) + { + builder.Property(package => package.Name).HasConversion(LocalizedStringConverter.Instance); + } + /// /// Applies the settings for the entity. /// diff --git a/src/Persistence/EntityFramework/Loading/GameConfigurationLoader.Generated.cs b/src/Persistence/EntityFramework/Loading/GameConfigurationLoader.Generated.cs index 071b36aaf..944a84782 100644 --- a/src/Persistence/EntityFramework/Loading/GameConfigurationLoader.Generated.cs +++ b/src/Persistence/EntityFramework/Loading/GameConfigurationLoader.Generated.cs @@ -422,7 +422,7 @@ internal sealed partial class GameConfigurationLoader entity.IsBundle = reader.GetBoolean(3); entity.IsForSale = reader.GetBoolean(4); entity.IsGiftable = reader.GetBoolean(5); - entity.Name = reader.GetString(6); + entity.Name = reader.IsDBNull(6) ? default : new global::MUnique.OpenMU.Interfaces.LocalizedString(reader.GetString(6)); entity.PackageSequence = reader.GetInt32(7); entity.Price = reader.GetInt32(8); this._CashShopPackage[entity.Id] = entity; diff --git a/src/Persistence/Initialization/Captions/ConfigurationCaptions.cs b/src/Persistence/Initialization/Captions/ConfigurationCaptions.cs index b6b2ab62f..5ec77fa41 100644 --- a/src/Persistence/Initialization/Captions/ConfigurationCaptions.cs +++ b/src/Persistence/Initialization/Captions/ConfigurationCaptions.cs @@ -169,6 +169,11 @@ internal static (string OwnerType, long Number, string PropertyName)? GetNumberK return (GetTypeName(set) + ":ArmorSet", ((long)armorNumber << 32) | (uint)set.SetLevel, caption.Property.Name); } + if (caption.Owner is CashShopPackage package) + { + return (GetTypeName(package), package.PackageSequence, caption.Property.Name); + } + var numberProperty = caption.Owner.GetType().GetProperty("Number"); return numberProperty?.GetValue(caption.Owner) is { } number and (byte or short or int or long or ushort) ? (GetTypeName(caption.Owner), Convert.ToInt64(number, CultureInfo.InvariantCulture), caption.Property.Name) diff --git a/src/Persistence/Initialization/ConfigurationNameSources.cs b/src/Persistence/Initialization/ConfigurationNameSources.cs index 97485edf4..540b17ca2 100644 --- a/src/Persistence/Initialization/ConfigurationNameSources.cs +++ b/src/Persistence/Initialization/ConfigurationNameSources.cs @@ -20,6 +20,7 @@ public static class ConfigurationNameSources /// public static void Register() { + RegisterIfNeeded(nameof(CashShopPackageNames), CashShopPackageNames.ResourceManager); RegisterIfNeeded(nameof(CharacterClassNames), CharacterClassNames.ResourceManager); RegisterIfNeeded(nameof(MapNames), MapNames.ResourceManager); RegisterIfNeeded(nameof(MerchantNames), MerchantNames.ResourceManager); diff --git a/src/Persistence/Initialization/MUnique.OpenMU.Persistence.Initialization.csproj b/src/Persistence/Initialization/MUnique.OpenMU.Persistence.Initialization.csproj index e6f672ca5..055c438de 100644 --- a/src/Persistence/Initialization/MUnique.OpenMU.Persistence.Initialization.csproj +++ b/src/Persistence/Initialization/MUnique.OpenMU.Persistence.Initialization.csproj @@ -446,4 +446,15 @@ WarpNames.resx + + + PublicResXFileCodeGenerator + CashShopPackageNames.Designer.cs + + + True + True + CashShopPackageNames.resx + + diff --git a/src/Persistence/Initialization/Properties/CashShopPackageNames.Designer.cs b/src/Persistence/Initialization/Properties/CashShopPackageNames.Designer.cs new file mode 100644 index 000000000..b1489030d --- /dev/null +++ b/src/Persistence/Initialization/Properties/CashShopPackageNames.Designer.cs @@ -0,0 +1,1887 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace MUnique.OpenMU.Persistence.Initialization.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// This class was generated by MSBuild using the GenerateResource task. + /// To add or remove a member, edit your .resx file then rerun MSBuild. + /// + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Build.Tasks.StronglyTypedResourceBuilder", "15.1.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class CashShopPackageNames { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal CashShopPackageNames() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MUnique.OpenMU.Persistence.Initialization.Properties.CashShopPackageNames", typeof(CashShopPackageNames).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)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to AG Boost Aura. + /// + public static string AGBoostAura { + get { + return ResourceManager.GetString("AGBoostAura", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Amethyst Ring. + /// + public static string AmethystRing { + get { + return ResourceManager.GetString("AmethystRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Blood Castle Ticket. + /// + public static string BloodCastleTicket { + get { + return ResourceManager.GetString("BloodCastleTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Blue] Gold Channel Package. + /// + public static string BlueGoldChannelPackage { + get { + return ResourceManager.GetString("BlueGoldChannelPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Gold Channel Ticket_30 Day]. + /// + public static string BonusGPGoldChannelTicket30Day { + get { + return ResourceManager.GetString("BonusGPGoldChannelTicket30Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Gold Channel Ticket_7 Day]. + /// + public static string BonusGPGoldChannelTicket7Day { + get { + return ResourceManager.GetString("BonusGPGoldChannelTicket7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Master Seal of Ascension_30 Day]. + /// + public static string BonusGPMasterSealofAscension30Day { + get { + return ResourceManager.GetString("BonusGPMasterSealofAscension30Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Master Seal of Ascension_7 Day]. + /// + public static string BonusGPMasterSealofAscension7Day { + get { + return ResourceManager.GetString("BonusGPMasterSealofAscension7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Master Seal of Wealth_30 Day]. + /// + public static string BonusGPMasterSealofWealth30Day { + get { + return ResourceManager.GetString("BonusGPMasterSealofWealth30Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Master Seal of Wealth_7 Day]. + /// + public static string BonusGPMasterSealofWealth7Day { + get { + return ResourceManager.GetString("BonusGPMasterSealofWealth7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Seal of Ascension_30 Day]. + /// + public static string BonusGPSealofAscension30Day { + get { + return ResourceManager.GetString("BonusGPSealofAscension30Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Seal of Ascension_7 Day]. + /// + public static string BonusGPSealofAscension7Day { + get { + return ResourceManager.GetString("BonusGPSealofAscension7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Seal of Wealth_30 Day]. + /// + public static string BonusGPSealofWealth30Day { + get { + return ResourceManager.GetString("BonusGPSealofWealth30Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [+GP][Seal of Wealth_7 Day]. + /// + public static string BonusGPSealofWealth7Day { + get { + return ResourceManager.GetString("BonusGPSealofWealth7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [AG Boost Aura]. + /// + public static string BracketedAGBoostAura { + get { + return ResourceManager.GetString("BracketedAGBoostAura", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Amethyst Ring]. + /// + public static string BracketedAmethystRing { + get { + return ResourceManager.GetString("BracketedAmethystRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Blood Castle Ticket]. + /// + public static string BracketedBloodCastleTicket { + get { + return ResourceManager.GetString("BracketedBloodCastleTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Chaos Card Gold]. + /// + public static string BracketedChaosCardGold { + get { + return ResourceManager.GetString("BracketedChaosCardGold", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Chaos Card Mini]. + /// + public static string BracketedChaosCardMini { + get { + return ResourceManager.GetString("BracketedChaosCardMini", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Critical Ring of Wizard]. + /// + public static string BracketedCriticalRingofWizard { + get { + return ResourceManager.GetString("BracketedCriticalRingofWizard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Demon]. + /// + public static string BracketedDemon { + get { + return ResourceManager.GetString("BracketedDemon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Devil Square Ticket]. + /// + public static string BracketedDevilSquareTicket { + get { + return ResourceManager.GetString("BracketedDevilSquareTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Elite Healing Potion]. + /// + public static string BracketedEliteHealingPotion { + get { + return ResourceManager.GetString("BracketedEliteHealingPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Elite Mana Potion]. + /// + public static string BracketedEliteManaPotion { + get { + return ResourceManager.GetString("BracketedEliteManaPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Elite SD Potion]. + /// + public static string BracketedEliteSDPotion { + get { + return ResourceManager.GetString("BracketedEliteSDPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Emerald Necklace]. + /// + public static string BracketedEmeraldNecklace { + get { + return ResourceManager.GetString("BracketedEmeraldNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Gladiator Package]. + /// + public static string BracketedGladiatorPackage { + get { + return ResourceManager.GetString("BracketedGladiatorPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Gold Channel Ticket]. + /// + public static string BracketedGoldChannelTicket { + get { + return ResourceManager.GetString("BracketedGoldChannelTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Golden Oak Charm]. + /// + public static string BracketedGoldenOakCharm { + get { + return ResourceManager.GetString("BracketedGoldenOakCharm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Gold Key]. + /// + public static string BracketedGoldKey { + get { + return ResourceManager.GetString("BracketedGoldKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Illusion Temple Ticket]. + /// + public static string BracketedIllusionTempleTicket { + get { + return ResourceManager.GetString("BracketedIllusionTempleTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Kalima Ticket]. + /// + public static string BracketedKalimaTicket { + get { + return ResourceManager.GetString("BracketedKalimaTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Level up (Master)]. + /// + public static string BracketedLevelupMaster { + get { + return ResourceManager.GetString("BracketedLevelupMaster", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Level up (normal)]. + /// + public static string BracketedLevelupnormal { + get { + return ResourceManager.GetString("BracketedLevelupnormal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Little Warrior's Cloak]. + /// + public static string BracketedLittleWarriorsCloak { + get { + return ResourceManager.GetString("BracketedLittleWarriorsCloak", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Magic Backpack]. + /// + public static string BracketedMagicBackpack { + get { + return ResourceManager.GetString("BracketedMagicBackpack", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Master Seal of Ascension]. + /// + public static string BracketedMasterSealofAscension { + get { + return ResourceManager.GetString("BracketedMasterSealofAscension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Master Seal of Wealth]. + /// + public static string BracketedMasterSealofWealth { + get { + return ResourceManager.GetString("BracketedMasterSealofWealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Oak Charm]. + /// + public static string BracketedOakCharm { + get { + return ResourceManager.GetString("BracketedOakCharm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Open Access Ticket to Varka 7]. + /// + public static string BracketedOpenAccessTickettoVarka7 { + get { + return ResourceManager.GetString("BracketedOpenAccessTickettoVarka7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Panda Ring]. + /// + public static string BracketedPandaRing { + get { + return ResourceManager.GetString("BracketedPandaRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Pet Panda]. + /// + public static string BracketedPetPanda { + get { + return ResourceManager.GetString("BracketedPetPanda", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Pet Skeleton]. + /// + public static string BracketedPetSkeleton { + get { + return ResourceManager.GetString("BracketedPetSkeleton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Pet Unicorn]. + /// + public static string BracketedPetUnicorn { + get { + return ResourceManager.GetString("BracketedPetUnicorn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Rage Fighter Character Card]. + /// + public static string BracketedRageFighterCharacterCard { + get { + return ResourceManager.GetString("BracketedRageFighterCharacterCard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Reset Fruit Control]. + /// + public static string BracketedResetFruitControl { + get { + return ResourceManager.GetString("BracketedResetFruitControl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Reset Fruit Energy]. + /// + public static string BracketedResetFruitEnergy { + get { + return ResourceManager.GetString("BracketedResetFruitEnergy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Reset Fruit Health]. + /// + public static string BracketedResetFruitHealth { + get { + return ResourceManager.GetString("BracketedResetFruitHealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Reset Fruit Quickness]. + /// + public static string BracketedResetFruitQuickness { + get { + return ResourceManager.GetString("BracketedResetFruitQuickness", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Reset Fruit Strength]. + /// + public static string BracketedResetFruitStrength { + get { + return ResourceManager.GetString("BracketedResetFruitStrength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Ruby Necklace]. + /// + public static string BracketedRubyNecklace { + get { + return ResourceManager.GetString("BracketedRubyNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Ruby Ring]. + /// + public static string BracketedRubyRing { + get { + return ResourceManager.GetString("BracketedRubyRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Sapphire Necklace]. + /// + public static string BracketedSapphireNecklace { + get { + return ResourceManager.GetString("BracketedSapphireNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Sapphire Ring]. + /// + public static string BracketedSapphireRing { + get { + return ResourceManager.GetString("BracketedSapphireRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Battle]. + /// + public static string BracketedScrollofBattle { + get { + return ResourceManager.GetString("BracketedScrollofBattle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Health]. + /// + public static string BracketedScrollofHealth { + get { + return ResourceManager.GetString("BracketedScrollofHealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Mana]. + /// + public static string BracketedScrollofMana { + get { + return ResourceManager.GetString("BracketedScrollofMana", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Protection]. + /// + public static string BracketedScrollofProtection { + get { + return ResourceManager.GetString("BracketedScrollofProtection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Quickness]. + /// + public static string BracketedScrollofQuickness { + get { + return ResourceManager.GetString("BracketedScrollofQuickness", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Strengthener]. + /// + public static string BracketedScrollofStrengthener { + get { + return ResourceManager.GetString("BracketedScrollofStrengthener", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Wizardry]. + /// + public static string BracketedScrollofWizardry { + get { + return ResourceManager.GetString("BracketedScrollofWizardry", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll of Wrath]. + /// + public static string BracketedScrollofWrath { + get { + return ResourceManager.GetString("BracketedScrollofWrath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll Package A]. + /// + public static string BracketedScrollPackageA { + get { + return ResourceManager.GetString("BracketedScrollPackageA", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll Package B]. + /// + public static string BracketedScrollPackageB { + get { + return ResourceManager.GetString("BracketedScrollPackageB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll Package C]. + /// + public static string BracketedScrollPackageC { + get { + return ResourceManager.GetString("BracketedScrollPackageC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Scroll Package D]. + /// + public static string BracketedScrollPackageD { + get { + return ResourceManager.GetString("BracketedScrollPackageD", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [SD Boost Aura]. + /// + public static string BracketedSDBoostAura { + get { + return ResourceManager.GetString("BracketedSDBoostAura", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Seal of Ascension]. + /// + public static string BracketedSealofAscension { + get { + return ResourceManager.GetString("BracketedSealofAscension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Seal of Divinity]. + /// + public static string BracketedSealofDivinity { + get { + return ResourceManager.GetString("BracketedSealofDivinity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Seal of Healing]. + /// + public static string BracketedSealofHealing { + get { + return ResourceManager.GetString("BracketedSealofHealing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Seal of Sustenance]. + /// + public static string BracketedSealofSustenance { + get { + return ResourceManager.GetString("BracketedSealofSustenance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Seal of Wealth]. + /// + public static string BracketedSealofWealth { + get { + return ResourceManager.GetString("BracketedSealofWealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Silver Key]. + /// + public static string BracketedSilverKey { + get { + return ResourceManager.GetString("BracketedSilverKey", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skeleton Transformation Ring]. + /// + public static string BracketedSkeletonTransformationRing { + get { + return ResourceManager.GetString("BracketedSkeletonTransformationRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Dark Knight]. + /// + public static string BracketedSkillbookpackageforDarkKnight { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforDarkKnight", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Dark Wizard]. + /// + public static string BracketedSkillbookpackageforDarkWizard { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforDarkWizard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Fairy Elf]. + /// + public static string BracketedSkillbookpackageforFairyElf { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforFairyElf", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Magic Gladiator]. + /// + public static string BracketedSkillbookpackageforMagicGladiator { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforMagicGladiator", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Rage Fighter]. + /// + public static string BracketedSkillbookpackageforRageFighter { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforRageFighter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Skill book package for Summoner]. + /// + public static string BracketedSkillbookpackageforSummoner { + get { + return ResourceManager.GetString("BracketedSkillbookpackageforSummoner", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Small Wings of Disaster]. + /// + public static string BracketedSmallWingsofDisaster { + get { + return ResourceManager.GetString("BracketedSmallWingsofDisaster", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Small Wings of Fairy]. + /// + public static string BracketedSmallWingsofFairy { + get { + return ResourceManager.GetString("BracketedSmallWingsofFairy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Small Wings of Heaven]. + /// + public static string BracketedSmallWingsofHeaven { + get { + return ResourceManager.GetString("BracketedSmallWingsofHeaven", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Small Wings of Satan]. + /// + public static string BracketedSmallWingsofSatan { + get { + return ResourceManager.GetString("BracketedSmallWingsofSatan", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Spirit of Guardian]. + /// + public static string BracketedSpiritofGuardian { + get { + return ResourceManager.GetString("BracketedSpiritofGuardian", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Statue of Goral]. + /// + public static string BracketedStatueofGoral { + get { + return ResourceManager.GetString("BracketedStatueofGoral", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Statue of Hawk]. + /// + public static string BracketedStatueofHawk { + get { + return ResourceManager.GetString("BracketedStatueofHawk", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Summoner Character Card]. + /// + public static string BracketedSummonerCharacterCard { + get { + return ResourceManager.GetString("BracketedSummonerCharacterCard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Talisman of Luck]. + /// + public static string BracketedTalismanofLuck { + get { + return ResourceManager.GetString("BracketedTalismanofLuck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Talisman of Mobility]. + /// + public static string BracketedTalismanofMobility { + get { + return ResourceManager.GetString("BracketedTalismanofMobility", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Talisman of Resurrection]. + /// + public static string BracketedTalismanofResurrection { + get { + return ResourceManager.GetString("BracketedTalismanofResurrection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Topaz Ring]. + /// + public static string BracketedTopazRing { + get { + return ResourceManager.GetString("BracketedTopazRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Vault Expansion Certificate]. + /// + public static string BracketedVaultExpansionCertificate { + get { + return ResourceManager.GetString("BracketedVaultExpansionCertificate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Wizard Ring]. + /// + public static string BracketedWizardRing { + get { + return ResourceManager.GetString("BracketedWizardRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Worn Horseshoe]. + /// + public static string BracketedWornHorseshoe { + get { + return ResourceManager.GetString("BracketedWornHorseshoe", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bundle of Jewel of Bless (30). + /// + public static string BundleofJewelofBless30 { + get { + return ResourceManager.GetString("BundleofJewelofBless30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bundle of Jewel of Harmony (10). + /// + public static string BundleofJewelofHarmony10 { + get { + return ResourceManager.GetString("BundleofJewelofHarmony10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Bundle of Jewel of Soul (30). + /// + public static string BundleofJewelofSoul30 { + get { + return ResourceManager.GetString("BundleofJewelofSoul30", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cherry Blossom Petal. + /// + public static string CherryBlossomPetal { + get { + return ResourceManager.GetString("CherryBlossomPetal", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cherry Blossom Rice Cake. + /// + public static string CherryBlossomRiceCake { + get { + return ResourceManager.GetString("CherryBlossomRiceCake", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Cherry Blossom Wine. + /// + public static string CherryBlossomWine { + get { + return ResourceManager.GetString("CherryBlossomWine", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Critical Ring of Wizard. + /// + public static string CriticalRingofWizard { + get { + return ResourceManager.GetString("CriticalRingofWizard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Demon. + /// + public static string Demon { + get { + return ResourceManager.GetString("Demon", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Devil Square Ticket. + /// + public static string DevilSquareTicket { + get { + return ResourceManager.GetString("DevilSquareTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elite Healing Potion. + /// + public static string EliteHealingPotion { + get { + return ResourceManager.GetString("EliteHealingPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elite Mana Potion. + /// + public static string EliteManaPotion { + get { + return ResourceManager.GetString("EliteManaPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Elite SD Potion. + /// + public static string EliteSDPotion { + get { + return ResourceManager.GetString("EliteSDPotion", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Emerald Necklace. + /// + public static string EmeraldNecklace { + get { + return ResourceManager.GetString("EmeraldNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1st Lucky Armor Ticket. + /// + public static string FirstLuckyArmorTicket { + get { + return ResourceManager.GetString("FirstLuckyArmorTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1st Lucky Boots Ticket. + /// + public static string FirstLuckyBootsTicket { + get { + return ResourceManager.GetString("FirstLuckyBootsTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1st Lucky Gloves Ticket. + /// + public static string FirstLuckyGlovesTicket { + get { + return ResourceManager.GetString("FirstLuckyGlovesTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1st Lucky Helm Ticket. + /// + public static string FirstLuckyHelmTicket { + get { + return ResourceManager.GetString("FirstLuckyHelmTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 1st Lucky Pants Ticket. + /// + public static string FirstLuckyPantsTicket { + get { + return ResourceManager.GetString("FirstLuckyPantsTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [5+1][Chaos Card Gold]. + /// + public static string FivePlusOneChaosCardGold { + get { + return ResourceManager.GetString("FivePlusOneChaosCardGold", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [5+1][Chaos Card Mini]. + /// + public static string FivePlusOneChaosCardMini { + get { + return ResourceManager.GetString("FivePlusOneChaosCardMini", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gladiator Package. + /// + public static string GladiatorPackage { + get { + return ResourceManager.GetString("GladiatorPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gold Channel Ticket. + /// + public static string GoldChannelTicket { + get { + return ResourceManager.GetString("GoldChannelTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Golden Oak Charm. + /// + public static string GoldenOakCharm { + get { + return ResourceManager.GetString("GoldenOakCharm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [GP]Box of Kundun +1. + /// + public static string GPBoxofKundunPlus1 { + get { + return ResourceManager.GetString("GPBoxofKundunPlus1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [GP]Box of kundun +2. + /// + public static string GPBoxofkundunPlus2 { + get { + return ResourceManager.GetString("GPBoxofkundunPlus2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [GP]Box of kundun +3. + /// + public static string GPBoxofkundunPlus3 { + get { + return ResourceManager.GetString("GPBoxofkundunPlus3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [GP]Box of kundun +4. + /// + public static string GPBoxofkundunPlus4 { + get { + return ResourceManager.GetString("GPBoxofkundunPlus4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [GP]Box of kundun +5. + /// + public static string GPBoxofkundunPlus5 { + get { + return ResourceManager.GetString("GPBoxofkundunPlus5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Illusion Temple Ticket. + /// + public static string IllusionTempleTicket { + get { + return ResourceManager.GetString("IllusionTempleTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Jewel of Chaos Bundle (10). + /// + public static string JewelofChaosBundle10 { + get { + return ResourceManager.GetString("JewelofChaosBundle10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Jewel of Life Bundle (10). + /// + public static string JewelofLifeBundle10 { + get { + return ResourceManager.GetString("JewelofLifeBundle10", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Kalima Ticket. + /// + public static string KalimaTicket { + get { + return ResourceManager.GetString("KalimaTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Little Warrior's Cloak. + /// + public static string LittleWarriorsCloak { + get { + return ResourceManager.GetString("LittleWarriorsCloak", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Magic Backpack. + /// + public static string MagicBackpack { + get { + return ResourceManager.GetString("MagicBackpack", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Master] eX700 OBT - Celebration Package. + /// + public static string MastereX700OBTCelebrationPackage { + get { + return ResourceManager.GetString("MastereX700OBTCelebrationPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Master Seal of Ascension. + /// + public static string MasterSealofAscension { + get { + return ResourceManager.GetString("MasterSealofAscension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Master Seal of Wealth. + /// + public static string MasterSealofWealth { + get { + return ResourceManager.GetString("MasterSealofWealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Normal] eX700 OBT - Celebration Package. + /// + public static string NormaleX700OBTCelebrationPackage { + get { + return ResourceManager.GetString("NormaleX700OBTCelebrationPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Oak Charm. + /// + public static string OakCharm { + get { + return ResourceManager.GetString("OakCharm", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open Access Ticket to Varka 7. + /// + public static string OpenAccessTickettoVarka7 { + get { + return ResourceManager.GetString("OpenAccessTickettoVarka7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Panda Ring. + /// + public static string PandaRing { + get { + return ResourceManager.GetString("PandaRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pet Panda. + /// + public static string PetPanda { + get { + return ResourceManager.GetString("PetPanda", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pet Skeleton. + /// + public static string PetSkeleton { + get { + return ResourceManager.GetString("PetSkeleton", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Pet Unicorn. + /// + public static string PetUnicorn { + get { + return ResourceManager.GetString("PetUnicorn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [Platinum] Gold Channel Package. + /// + public static string PlatinumGoldChannelPackage { + get { + return ResourceManager.GetString("PlatinumGoldChannelPackage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Premium Service. + /// + public static string PremiumService { + get { + return ResourceManager.GetString("PremiumService", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rage Fighter Character Card. + /// + public static string RageFighterCharacterCard { + get { + return ResourceManager.GetString("RageFighterCharacterCard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rare Item Ticket 11. + /// + public static string RareItemTicket11 { + get { + return ResourceManager.GetString("RareItemTicket11", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rare Item Ticket 8. + /// + public static string RareItemTicket8 { + get { + return ResourceManager.GetString("RareItemTicket8", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Fruit Control. + /// + public static string ResetFruitControl { + get { + return ResourceManager.GetString("ResetFruitControl", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Fruit Energy. + /// + public static string ResetFruitEnergy { + get { + return ResourceManager.GetString("ResetFruitEnergy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Fruit Health. + /// + public static string ResetFruitHealth { + get { + return ResourceManager.GetString("ResetFruitHealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Fruit Quickness. + /// + public static string ResetFruitQuickness { + get { + return ResourceManager.GetString("ResetFruitQuickness", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Reset Fruit Strength. + /// + public static string ResetFruitStrength { + get { + return ResourceManager.GetString("ResetFruitStrength", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ruby Necklace. + /// + public static string RubyNecklace { + get { + return ResourceManager.GetString("RubyNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ruby Ring. + /// + public static string RubyRing { + get { + return ResourceManager.GetString("RubyRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sapphire Necklace. + /// + public static string SapphireNecklace { + get { + return ResourceManager.GetString("SapphireNecklace", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sapphire Ring. + /// + public static string SapphireRing { + get { + return ResourceManager.GetString("SapphireRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Battle. + /// + public static string ScrollofBattle { + get { + return ResourceManager.GetString("ScrollofBattle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Battle_7 Day. + /// + public static string ScrollofBattle7Day { + get { + return ResourceManager.GetString("ScrollofBattle7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Health. + /// + public static string ScrollofHealth { + get { + return ResourceManager.GetString("ScrollofHealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Health_7 Day. + /// + public static string ScrollofHealth7Day { + get { + return ResourceManager.GetString("ScrollofHealth7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Mana. + /// + public static string ScrollofMana { + get { + return ResourceManager.GetString("ScrollofMana", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Mana_7 Day. + /// + public static string ScrollofMana7Day { + get { + return ResourceManager.GetString("ScrollofMana7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Protection. + /// + public static string ScrollofProtection { + get { + return ResourceManager.GetString("ScrollofProtection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Protection_7 Day. + /// + public static string ScrollofProtection7Day { + get { + return ResourceManager.GetString("ScrollofProtection7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Quickness. + /// + public static string ScrollofQuickness { + get { + return ResourceManager.GetString("ScrollofQuickness", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Quickness_7 Day. + /// + public static string ScrollofQuickness7Day { + get { + return ResourceManager.GetString("ScrollofQuickness7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Strengthener. + /// + public static string ScrollofStrengthener { + get { + return ResourceManager.GetString("ScrollofStrengthener", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Strengthener_7 Day. + /// + public static string ScrollofStrengthener7Day { + get { + return ResourceManager.GetString("ScrollofStrengthener7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Wizardry. + /// + public static string ScrollofWizardry { + get { + return ResourceManager.GetString("ScrollofWizardry", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Wizardry_7 Day. + /// + public static string ScrollofWizardry7Day { + get { + return ResourceManager.GetString("ScrollofWizardry7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Wrath. + /// + public static string ScrollofWrath { + get { + return ResourceManager.GetString("ScrollofWrath", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll of Wrath_7 Day. + /// + public static string ScrollofWrath7Day { + get { + return ResourceManager.GetString("ScrollofWrath7Day", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll Package A. + /// + public static string ScrollPackageA { + get { + return ResourceManager.GetString("ScrollPackageA", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll Package B. + /// + public static string ScrollPackageB { + get { + return ResourceManager.GetString("ScrollPackageB", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll Package C. + /// + public static string ScrollPackageC { + get { + return ResourceManager.GetString("ScrollPackageC", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Scroll Package D. + /// + public static string ScrollPackageD { + get { + return ResourceManager.GetString("ScrollPackageD", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to SD Boost Aura. + /// + public static string SDBoostAura { + get { + return ResourceManager.GetString("SDBoostAura", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seal of Ascension. + /// + public static string SealofAscension { + get { + return ResourceManager.GetString("SealofAscension", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seal of Divinity. + /// + public static string SealofDivinity { + get { + return ResourceManager.GetString("SealofDivinity", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seal of Healing. + /// + public static string SealofHealing { + get { + return ResourceManager.GetString("SealofHealing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seal of Sustenance. + /// + public static string SealofSustenance { + get { + return ResourceManager.GetString("SealofSustenance", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Seal of Wealth. + /// + public static string SealofWealth { + get { + return ResourceManager.GetString("SealofWealth", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2nd Lucky Armor Ticket. + /// + public static string SecondLuckyArmorTicket { + get { + return ResourceManager.GetString("SecondLuckyArmorTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2nd Lucky Boots Ticket. + /// + public static string SecondLuckyBootsTicket { + get { + return ResourceManager.GetString("SecondLuckyBootsTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2nd Lucky Gloves Ticket. + /// + public static string SecondLuckyGlovesTicket { + get { + return ResourceManager.GetString("SecondLuckyGlovesTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2nd Lucky Helm Ticket. + /// + public static string SecondLuckyHelmTicket { + get { + return ResourceManager.GetString("SecondLuckyHelmTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 2nd Lucky Pants Ticket. + /// + public static string SecondLuckyPantsTicket { + get { + return ResourceManager.GetString("SecondLuckyPantsTicket", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Skeleton Transformation Ring. + /// + public static string SkeletonTransformationRing { + get { + return ResourceManager.GetString("SkeletonTransformationRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Small Wings of Disaster. + /// + public static string SmallWingsofDisaster { + get { + return ResourceManager.GetString("SmallWingsofDisaster", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Small Wings of Fairy. + /// + public static string SmallWingsofFairy { + get { + return ResourceManager.GetString("SmallWingsofFairy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Small Wings of Heaven. + /// + public static string SmallWingsofHeaven { + get { + return ResourceManager.GetString("SmallWingsofHeaven", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Small Wings of Satan. + /// + public static string SmallWingsofSatan { + get { + return ResourceManager.GetString("SmallWingsofSatan", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Spirit of Guardian. + /// + public static string SpiritofGuardian { + get { + return ResourceManager.GetString("SpiritofGuardian", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Statue of Goral. + /// + public static string StatueofGoral { + get { + return ResourceManager.GetString("StatueofGoral", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Statue of Hawk. + /// + public static string StatueofHawk { + get { + return ResourceManager.GetString("StatueofHawk", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Summoner Character Card. + /// + public static string SummonerCharacterCard { + get { + return ResourceManager.GetString("SummonerCharacterCard", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Talisman of Luck. + /// + public static string TalismanofLuck { + get { + return ResourceManager.GetString("TalismanofLuck", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Talisman of Luck 10%. + /// + public static string TalismanofLuck10Percent { + get { + return ResourceManager.GetString("TalismanofLuck10Percent", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Talisman of Mobility. + /// + public static string TalismanofMobility { + get { + return ResourceManager.GetString("TalismanofMobility", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Talisman of Resurrection. + /// + public static string TalismanofResurrection { + get { + return ResourceManager.GetString("TalismanofResurrection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [10+3][Chaos Card Gold]. + /// + public static string TenPlusThreeChaosCardGold { + get { + return ResourceManager.GetString("TenPlusThreeChaosCardGold", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to [10+3][Chaos Card Mini]. + /// + public static string TenPlusThreeChaosCardMini { + get { + return ResourceManager.GetString("TenPlusThreeChaosCardMini", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Topaz Ring. + /// + public static string TopazRing { + get { + return ResourceManager.GetString("TopazRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Vault Expansion Certificate. + /// + public static string VaultExpansionCertificate { + get { + return ResourceManager.GetString("VaultExpansionCertificate", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Wizard Ring. + /// + public static string WizardRing { + get { + return ResourceManager.GetString("WizardRing", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Worn Horseshoe. + /// + public static string WornHorseshoe { + get { + return ResourceManager.GetString("WornHorseshoe", resourceCulture); + } + } + } +} diff --git a/src/Persistence/Initialization/Properties/CashShopPackageNames.resx b/src/Persistence/Initialization/Properties/CashShopPackageNames.resx new file mode 100644 index 000000000..ac4921c2f --- /dev/null +++ b/src/Persistence/Initialization/Properties/CashShopPackageNames.resx @@ -0,0 +1,616 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms + System.Resources.ResXResourceWriter, System.Windows.Forms + + AG Boost Aura + + + Amethyst Ring + + + Blood Castle Ticket + + + [Blue] Gold Channel Package + + + [+GP][Gold Channel Ticket_30 Day] + + + [+GP][Gold Channel Ticket_7 Day] + + + [+GP][Master Seal of Ascension_30 Day] + + + [+GP][Master Seal of Ascension_7 Day] + + + [+GP][Master Seal of Wealth_30 Day] + + + [+GP][Master Seal of Wealth_7 Day] + + + [+GP][Seal of Ascension_30 Day] + + + [+GP][Seal of Ascension_7 Day] + + + [+GP][Seal of Wealth_30 Day] + + + [+GP][Seal of Wealth_7 Day] + + + [AG Boost Aura] + + + [Amethyst Ring] + + + [Blood Castle Ticket] + + + [Chaos Card Gold] + + + [Chaos Card Mini] + + + [Critical Ring of Wizard] + + + [Demon] + + + [Devil Square Ticket] + + + [Elite Healing Potion] + + + [Elite Mana Potion] + + + [Elite SD Potion] + + + [Emerald Necklace] + + + [Gladiator Package] + + + [Gold Channel Ticket] + + + [Gold Key] + + + [Golden Oak Charm] + + + [Illusion Temple Ticket] + + + [Kalima Ticket] + + + [Level up (Master)] + + + [Level up (normal)] + + + [Little Warrior's Cloak] + + + [Magic Backpack] + + + [Master Seal of Ascension] + + + [Master Seal of Wealth] + + + [Oak Charm] + + + [Open Access Ticket to Varka 7] + + + [Panda Ring] + + + [Pet Panda] + + + [Pet Skeleton] + + + [Pet Unicorn] + + + [Rage Fighter Character Card] + + + [Reset Fruit Control] + + + [Reset Fruit Energy] + + + [Reset Fruit Health] + + + [Reset Fruit Quickness] + + + [Reset Fruit Strength] + + + [Ruby Necklace] + + + [Ruby Ring] + + + [SD Boost Aura] + + + [Sapphire Necklace] + + + [Sapphire Ring] + + + [Scroll Package A] + + + [Scroll Package B] + + + [Scroll Package C] + + + [Scroll Package D] + + + [Scroll of Battle] + + + [Scroll of Health] + + + [Scroll of Mana] + + + [Scroll of Protection] + + + [Scroll of Quickness] + + + [Scroll of Strengthener] + + + [Scroll of Wizardry] + + + [Scroll of Wrath] + + + [Seal of Ascension] + + + [Seal of Divinity] + + + [Seal of Healing] + + + [Seal of Sustenance] + + + [Seal of Wealth] + + + [Silver Key] + + + [Skeleton Transformation Ring] + + + [Skill book package for Dark Knight] + + + [Skill book package for Dark Wizard] + + + [Skill book package for Fairy Elf] + + + [Skill book package for Magic Gladiator] + + + [Skill book package for Rage Fighter] + + + [Skill book package for Summoner] + + + [Small Wings of Disaster] + + + [Small Wings of Fairy] + + + [Small Wings of Heaven] + + + [Small Wings of Satan] + + + [Spirit of Guardian] + + + [Statue of Goral] + + + [Statue of Hawk] + + + [Summoner Character Card] + + + [Talisman of Luck] + + + [Talisman of Mobility] + + + [Talisman of Resurrection] + + + [Topaz Ring] + + + [Vault Expansion Certificate] + + + [Wizard Ring] + + + [Worn Horseshoe] + + + Bundle of Jewel of Bless (30) + + + Bundle of Jewel of Harmony (10) + + + Bundle of Jewel of Soul (30) + + + Cherry Blossom Petal + + + Cherry Blossom Rice Cake + + + Cherry Blossom Wine + + + Critical Ring of Wizard + + + Demon + + + Devil Square Ticket + + + Elite Healing Potion + + + Elite Mana Potion + + + Elite SD Potion + + + Emerald Necklace + + + 1st Lucky Armor Ticket + + + 1st Lucky Boots Ticket + + + 1st Lucky Gloves Ticket + + + 1st Lucky Helm Ticket + + + 1st Lucky Pants Ticket + + + [5+1][Chaos Card Gold] + + + [5+1][Chaos Card Mini] + + + [GP]Box of Kundun +1 + + + [GP]Box of kundun +2 + + + [GP]Box of kundun +3 + + + [GP]Box of kundun +4 + + + [GP]Box of kundun +5 + + + Gladiator Package + + + Gold Channel Ticket + + + Golden Oak Charm + + + Illusion Temple Ticket + + + Jewel of Chaos Bundle (10) + + + Jewel of Life Bundle (10) + + + Kalima Ticket + + + Little Warrior's Cloak + + + Magic Backpack + + + Master Seal of Ascension + + + Master Seal of Wealth + + + [Master] eX700 OBT - Celebration Package + + + [Normal] eX700 OBT - Celebration Package + + + Oak Charm + + + Open Access Ticket to Varka 7 + + + Panda Ring + + + Pet Panda + + + Pet Skeleton + + + Pet Unicorn + + + [Platinum] Gold Channel Package + + + Premium Service + + + Rage Fighter Character Card + + + Rare Item Ticket 11 + + + Rare Item Ticket 8 + + + Reset Fruit Control + + + Reset Fruit Energy + + + Reset Fruit Health + + + Reset Fruit Quickness + + + Reset Fruit Strength + + + Ruby Necklace + + + Ruby Ring + + + SD Boost Aura + + + Sapphire Necklace + + + Sapphire Ring + + + Scroll Package A + + + Scroll Package B + + + Scroll Package C + + + Scroll Package D + + + Scroll of Battle + + + Scroll of Battle_7 Day + + + Scroll of Health + + + Scroll of Health_7 Day + + + Scroll of Mana + + + Scroll of Mana_7 Day + + + Scroll of Protection + + + Scroll of Protection_7 Day + + + Scroll of Quickness + + + Scroll of Quickness_7 Day + + + Scroll of Strengthener + + + Scroll of Strengthener_7 Day + + + Scroll of Wizardry + + + Scroll of Wizardry_7 Day + + + Scroll of Wrath + + + Scroll of Wrath_7 Day + + + Seal of Ascension + + + Seal of Divinity + + + Seal of Healing + + + Seal of Sustenance + + + Seal of Wealth + + + 2nd Lucky Armor Ticket + + + 2nd Lucky Boots Ticket + + + 2nd Lucky Gloves Ticket + + + 2nd Lucky Helm Ticket + + + 2nd Lucky Pants Ticket + + + Skeleton Transformation Ring + + + Small Wings of Disaster + + + Small Wings of Fairy + + + Small Wings of Heaven + + + Small Wings of Satan + + + Spirit of Guardian + + + Statue of Goral + + + Statue of Hawk + + + Summoner Character Card + + + Talisman of Luck + + + Talisman of Luck 10% + + + Talisman of Mobility + + + Talisman of Resurrection + + + [10+3][Chaos Card Gold] + + + [10+3][Chaos Card Mini] + + + Topaz Ring + + + Vault Expansion Certificate + + + Wizard Ring + + + Worn Horseshoe + + diff --git a/src/Persistence/Initialization/Properties/CashShopPackageNames.zh-CN.resx b/src/Persistence/Initialization/Properties/CashShopPackageNames.zh-CN.resx new file mode 100644 index 000000000..f78d3a384 --- /dev/null +++ b/src/Persistence/Initialization/Properties/CashShopPackageNames.zh-CN.resx @@ -0,0 +1,616 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms + System.Resources.ResXResourceWriter, System.Windows.Forms + + 最大AG提升光环 + + + 紫水晶指环 + + + 血色城堡入场券 + + + [蓝色] 黄金频道礼包 + + + [+GP][黄金频道入场券(30天)] + + + [+GP][黄金频道入场券(7天)] + + + [+GP][大师等级经验印章(30天)] + + + [+GP][大师等级经验印章(7天)] + + + [+GP][大师等级神圣印章(30天)] + + + [+GP][大师等级神圣印章(7天)] + + + [+GP][经验印章(30天)] + + + [+GP][经验印章(7天)] + + + [+GP][神圣印章(30天)] + + + [+GP][神圣印章(7天)] + + + [最大AG提升光环] + + + [紫水晶指环] + + + [血色城堡入场券] + + + [黄金玛雅卡片] + + + [迷你玛雅卡片] + + + [巫师致命指环] + + + [恶魔] + + + [恶魔广场入场券] + + + [精华治疗药水] + + + [精华魔力药水] + + + [精华SD药水] + + + [绿宝石项链] + + + [角斗士礼包] + + + [黄金频道入场券] + + + [黄金钥匙] + + + [黄金橡木护符] + + + [幻影寺院入场券] + + + [卡利玛入场券] + + + [升级礼包(大师)] + + + [升级礼包(普通)] + + + [小武者披风] + + + [魔法背包] + + + [大师等级经验印章] + + + [大师等级神圣印章] + + + [橡木护符] + + + [帝国要塞7自由入场券] + + + [熊猫变身指环] + + + [熊猫] + + + [幼龙骨架] + + + [独角兽] + + + [格斗家角色卡] + + + [统率洗点果实] + + + [智力洗点果实] + + + [体力洗点果实] + + + [敏捷洗点果实] + + + [力量洗点果实] + + + [红宝石项链] + + + [红宝石指环] + + + [最大SD提升光环] + + + [蓝宝石项链] + + + [蓝宝石指环] + + + [卷轴礼包A] + + + [卷轴礼包B] + + + [卷轴礼包C] + + + [卷轴礼包D] + + + [幸运一击卷轴] + + + [生命卷轴] + + + [魔法卷轴] + + + [防御卷轴] + + + [速度卷轴] + + + [卓越一击卷轴] + + + [魔力卷轴] + + + [攻击卷轴] + + + [经验印章] + + + [神性印章] + + + [恢复印章] + + + [持续印章] + + + [神圣印章] + + + [白银钥匙] + + + [骨架变身指环] + + + [剑士技能书礼包] + + + [魔法师技能书礼包] + + + [弓箭手技能书礼包] + + + [魔剑士技能书礼包] + + + [格斗家技能书礼包] + + + [召唤术师技能书礼包] + + + [小灾难之翼] + + + [小精灵之翼] + + + [小天使之翼] + + + [小恶魔之翼] + + + [守护精灵] + + + [斑羚雕像] + + + [鹰雕像] + + + [召唤术师角色卡] + + + [幸运符咒] + + + [移动符咒] + + + [复活符咒] + + + [黄宝石指环] + + + [仓库扩展证书] + + + [巫师指环] + + + [磨损的马蹄铁] + + + 祝福宝石组合(30颗) + + + 再生宝石组合(10颗) + + + 灵魂宝石组合(30颗) + + + 樱花花瓣 + + + 樱花年糕 + + + 樱花酒 + + + 巫师致命指环 + + + 恶魔 + + + 恶魔广场入场券 + + + 精华治疗药水 + + + 精华魔力药水 + + + 精华SD药水 + + + 绿宝石项链 + + + 一代幸运装备兑换券(铠) + + + 一代幸运装备兑换券(靴) + + + 一代幸运装备兑换券(护手) + + + 一代幸运装备兑换券(盔) + + + 一代幸运装备兑换券(护腿) + + + [5+1][黄金玛雅卡片] + + + [5+1][迷你玛雅卡片] + + + [GP]昆顿宝箱 +1 + + + [GP]昆顿宝箱 +2 + + + [GP]昆顿宝箱 +3 + + + [GP]昆顿宝箱 +4 + + + [GP]昆顿宝箱 +5 + + + 角斗士礼包 + + + 黄金频道入场券 + + + 黄金橡木护符 + + + 幻影寺院入场券 + + + 玛雅之石组合(10颗) + + + 生命宝石组合(10颗) + + + 卡利玛入场券 + + + 小武者披风 + + + 魔法背包 + + + 大师等级经验印章 + + + 大师等级神圣印章 + + + [大师] eX700公测庆典礼包 + + + [普通] eX700公测庆典礼包 + + + 橡木护符 + + + 帝国要塞7自由入场券 + + + 熊猫变身指环 + + + 熊猫 + + + 幼龙骨架 + + + 独角兽 + + + [白金] 黄金频道礼包 + + + 高级服务 + + + 格斗家角色卡 + + + 稀有物品兑换券11 + + + 稀有物品兑换券8 + + + 统率洗点果实 + + + 智力洗点果实 + + + 体力洗点果实 + + + 敏捷洗点果实 + + + 力量洗点果实 + + + 红宝石项链 + + + 红宝石指环 + + + 最大SD提升光环 + + + 蓝宝石项链 + + + 蓝宝石指环 + + + 卷轴礼包A + + + 卷轴礼包B + + + 卷轴礼包C + + + 卷轴礼包D + + + 幸运一击卷轴 + + + 幸运一击卷轴(7天) + + + 生命卷轴 + + + 生命卷轴(7天) + + + 魔法卷轴 + + + 魔法卷轴(7天) + + + 防御卷轴 + + + 防御卷轴(7天) + + + 速度卷轴 + + + 速度卷轴(7天) + + + 卓越一击卷轴 + + + 卓越一击卷轴(7天) + + + 魔力卷轴 + + + 魔力卷轴(7天) + + + 攻击卷轴 + + + 攻击卷轴(7天) + + + 经验印章 + + + 神性印章 + + + 恢复印章 + + + 持续印章 + + + 神圣印章 + + + 二代幸运装备兑换券(铠) + + + 二代幸运装备兑换券(靴) + + + 二代幸运装备兑换券(护手) + + + 二代幸运装备兑换券(盔) + + + 二代幸运装备兑换券(护腿) + + + 骨架变身指环 + + + 小灾难之翼 + + + 小精灵之翼 + + + 小天使之翼 + + + 小恶魔之翼 + + + 守护精灵 + + + 斑羚雕像 + + + 鹰雕像 + + + 召唤术师角色卡 + + + 幸运符咒 + + + 幸运符咒10% + + + 移动符咒 + + + 复活符咒 + + + [10+3][黄金玛雅卡片] + + + [10+3][迷你玛雅卡片] + + + 黄宝石指环 + + + 仓库扩展证书 + + + 巫师指环 + + + 磨损的马蹄铁 + + diff --git a/src/Persistence/Initialization/VersionSeasonSix/CashShopInitializer.cs b/src/Persistence/Initialization/VersionSeasonSix/CashShopInitializer.cs index f0e39d515..a6de44e4f 100644 --- a/src/Persistence/Initialization/VersionSeasonSix/CashShopInitializer.cs +++ b/src/Persistence/Initialization/VersionSeasonSix/CashShopInitializer.cs @@ -6,6 +6,7 @@ namespace MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.GameLogic.CashShop; +using MUnique.OpenMU.Interfaces; /// /// Initializes the cash shop configuration. @@ -68,18 +69,18 @@ public override void Initialize() private void AddPackages(CashShopConfiguration configuration) { - this.AddPackage(configuration, 413, "Gold Channel Ticket", 190, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 413, LocalizedString.FromResource(() => CashShopPackageNames.GoldChannelTicket), 190, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(528, 607, 190, 13, 124, 0, 1, 86400) .AddProduct(528, 608, 400, 13, 124, 0, 1, 259200) .AddProduct(528, 609, 800, 13, 124, 0, 1, 604800) .AddProduct(528, 610, 2300, 13, 124, 0, 1, 2592000); - this.AddPackage(configuration, 260, "Magic Backpack", 690, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 260, LocalizedString.FromResource(() => CashShopPackageNames.MagicBackpack), 690, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(281, 349, 690, 14, 162, 0, 1, 0); - this.AddPackage(configuration, 258, "Vault Expansion Certificate", 2490, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 258, LocalizedString.FromResource(() => CashShopPackageNames.VaultExpansionCertificate), 2490, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(282, 350, 2490, 14, 163, 0, 1, 0); - this.AddPackage(configuration, 187, "Premium Service", 0, CashShopCoinType.WCoinC, isForSale: false, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 187, LocalizedString.FromResource(() => CashShopPackageNames.PremiumService), 0, CashShopCoinType.WCoinC, isForSale: false, isGiftable: false, isBundle: false) .AddProduct(149, 209, 0, 14, 137, 0, 1, 0); - this.AddPackage(configuration, 162, "Gladiator Package", 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) + this.AddPackage(configuration, 162, LocalizedString.FromResource(() => CashShopPackageNames.GladiatorPackage), 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) .AddProduct(115, 174, 0, 14, 72, 0, 1, 86400) .AddProduct(116, 175, 0, 14, 133, 0, 10, 0) .AddProduct(118, 177, 130, 13, 107, 0, 1, 86400) @@ -87,238 +88,238 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(120, 179, 150, 14, 98, 0, 1, 86400) .AddProduct(121, 180, 120, 13, 105, 0, 1, 86400) .AddProduct(122, 181, 0, 13, 113, 0, 1, 86400); - this.AddPackage(configuration, 98, "Talisman of Luck", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 98, LocalizedString.FromResource(() => CashShopPackageNames.TalismanofLuck), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(22, 37, 100, 14, 53, 0, 1, 0) .AddProduct(22, 38, 400, 14, 53, 0, 1, 0); - this.AddPackage(configuration, 114, "Reset Fruit Strength", 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 114, LocalizedString.FromResource(() => CashShopPackageNames.ResetFruitStrength), 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(14, 24, 250, 13, 54, 0, 1, 0); - this.AddPackage(configuration, 112, "Reset Fruit Quickness", 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 112, LocalizedString.FromResource(() => CashShopPackageNames.ResetFruitQuickness), 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(15, 25, 250, 13, 55, 0, 1, 0); - this.AddPackage(configuration, 110, "Reset Fruit Health", 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 110, LocalizedString.FromResource(() => CashShopPackageNames.ResetFruitHealth), 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(16, 26, 250, 13, 56, 0, 1, 0); - this.AddPackage(configuration, 108, "Reset Fruit Energy", 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 108, LocalizedString.FromResource(() => CashShopPackageNames.ResetFruitEnergy), 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(17, 27, 250, 13, 57, 0, 1, 0); - this.AddPackage(configuration, 106, "Reset Fruit Control", 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 106, LocalizedString.FromResource(() => CashShopPackageNames.ResetFruitControl), 250, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(18, 28, 250, 13, 58, 0, 1, 0); - this.AddPackage(configuration, 263, "Rage Fighter Character Card", 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 263, LocalizedString.FromResource(() => CashShopPackageNames.RageFighterCharacterCard), 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(284, 353, 500, 14, 169, 0, 1, 0); - this.AddPackage(configuration, 126, "Summoner Character Card", 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 126, LocalizedString.FromResource(() => CashShopPackageNames.SummonerCharacterCard), 500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(31, 53, 500, 14, 91, 0, 1, 0); - this.AddPackage(configuration, 70, "Talisman of Resurrection", 50, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 70, LocalizedString.FromResource(() => CashShopPackageNames.TalismanofResurrection), 50, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(40, 66, 50, 13, 69, 0, 1, 0); - this.AddPackage(configuration, 68, "Talisman of Mobility", 40, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 68, LocalizedString.FromResource(() => CashShopPackageNames.TalismanofMobility), 40, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(41, 67, 40, 13, 70, 0, 1, 0); - this.AddPackage(configuration, 122, "Seal of Wealth", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 122, LocalizedString.FromResource(() => CashShopPackageNames.SealofWealth), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(10, 13, 150, 13, 44, 0, 1, 86400) .AddProduct(10, 14, 350, 13, 44, 0, 1, 259200) .AddProduct(10, 15, 700, 13, 44, 0, 1, 604800) .AddProduct(10, 16, 2100, 13, 44, 0, 1, 2592000); - this.AddPackage(configuration, 124, "Seal of Ascension", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 124, LocalizedString.FromResource(() => CashShopPackageNames.SealofAscension), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(9, 9, 100, 13, 43, 0, 1, 86400) .AddProduct(9, 10, 250, 13, 43, 0, 1, 259200) .AddProduct(9, 11, 500, 13, 43, 0, 1, 604800) .AddProduct(9, 12, 1400, 13, 43, 0, 1, 2592000); - this.AddPackage(configuration, 48, "Master Seal of Wealth", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 48, LocalizedString.FromResource(() => CashShopPackageNames.MasterSealofWealth), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(51, 80, 150, 13, 94, 0, 1, 86400) .AddProduct(51, 81, 700, 13, 94, 0, 1, 604800) .AddProduct(51, 82, 2100, 13, 94, 0, 1, 2592000); - this.AddPackage(configuration, 50, "Master Seal of Ascension", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 50, LocalizedString.FromResource(() => CashShopPackageNames.MasterSealofAscension), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(50, 77, 100, 13, 93, 0, 1, 86400) .AddProduct(50, 78, 500, 13, 93, 0, 1, 604800) .AddProduct(50, 79, 1400, 13, 93, 0, 1, 2592000); - this.AddPackage(configuration, 120, "Seal of Sustenance", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 120, LocalizedString.FromResource(() => CashShopPackageNames.SealofSustenance), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(11, 17, 80, 13, 45, 0, 1, 86400) .AddProduct(11, 18, 680, 13, 45, 0, 1, 864000) .AddProduct(11, 19, 1250, 13, 45, 0, 1, 2592000); - this.AddPackage(configuration, 74, "Seal of Healing", 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 74, LocalizedString.FromResource(() => CashShopPackageNames.SealofHealing), 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(38, 62, 120, 13, 62, 0, 1, 86400) .AddProduct(38, 63, 600, 13, 62, 0, 1, 604800); - this.AddPackage(configuration, 72, "Seal of Divinity", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 72, LocalizedString.FromResource(() => CashShopPackageNames.SealofDivinity), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(39, 64, 100, 13, 63, 0, 1, 86400) .AddProduct(39, 65, 500, 13, 63, 0, 1, 604800); - this.AddPackage(configuration, 9, "AG Boost Aura", 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 9, LocalizedString.FromResource(() => CashShopPackageNames.AGBoostAura), 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(73, 123, 120, 13, 104, 0, 1, 86400) .AddProduct(73, 124, 600, 13, 104, 0, 1, 604800); - this.AddPackage(configuration, 6, "SD Boost Aura", 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 6, LocalizedString.FromResource(() => CashShopPackageNames.SDBoostAura), 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(74, 125, 120, 13, 105, 0, 1, 86400) .AddProduct(74, 126, 600, 13, 105, 0, 1, 604800); - this.AddPackage(configuration, 356, "Worn Horseshoe", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 356, LocalizedString.FromResource(() => CashShopPackageNames.WornHorseshoe), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(463, 540, 80, 13, 134, 0, 1, 86400) .AddProduct(463, 541, 400, 13, 134, 0, 1, 604800) .AddProduct(463, 542, 1200, 13, 134, 0, 1, 2592000); - this.AddPackage(configuration, 354, "Golden Oak Charm", 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 354, LocalizedString.FromResource(() => CashShopPackageNames.GoldenOakCharm), 120, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(462, 537, 120, 13, 132, 0, 1, 86400) .AddProduct(462, 538, 600, 13, 132, 0, 1, 604800) .AddProduct(462, 539, 1800, 13, 132, 0, 1, 2592000); - this.AddPackage(configuration, 352, "Oak Charm", 30, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 352, LocalizedString.FromResource(() => CashShopPackageNames.OakCharm), 30, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(461, 534, 30, 13, 130, 0, 1, 86400) .AddProduct(461, 535, 150, 13, 130, 0, 1, 604800) .AddProduct(461, 536, 500, 13, 130, 0, 1, 2592000); - this.AddPackage(configuration, 348, "Statue of Hawk", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 348, LocalizedString.FromResource(() => CashShopPackageNames.StatueofHawk), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(459, 528, 80, 13, 128, 0, 1, 86400) .AddProduct(459, 529, 400, 13, 128, 0, 1, 604800) .AddProduct(459, 530, 1200, 13, 128, 0, 1, 2592000); - this.AddPackage(configuration, 350, "Statue of Goral", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 350, LocalizedString.FromResource(() => CashShopPackageNames.StatueofGoral), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(460, 531, 80, 13, 129, 0, 1, 86400) .AddProduct(460, 532, 400, 13, 129, 0, 1, 604800) .AddProduct(460, 533, 1200, 13, 129, 0, 1, 2592000); - this.AddPackage(configuration, 197, "Scroll Package A", 320, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) + this.AddPackage(configuration, 197, LocalizedString.FromResource(() => CashShopPackageNames.ScrollPackageA), 320, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) .AddProduct(159, 219, 120, 14, 74, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400); - this.AddPackage(configuration, 199, "Scroll Package B", 320, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) + this.AddPackage(configuration, 199, LocalizedString.FromResource(() => CashShopPackageNames.ScrollPackageB), 320, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) .AddProduct(158, 218, 120, 14, 75, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400); - this.AddPackage(configuration, 201, "Scroll Package C", 488, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) + this.AddPackage(configuration, 201, LocalizedString.FromResource(() => CashShopPackageNames.ScrollPackageC), 488, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) .AddProduct(156, 216, 56, 14, 77, 0, 1, 86400) .AddProduct(157, 217, 56, 14, 76, 0, 1, 86400) .AddProduct(159, 219, 120, 14, 74, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400) .AddProduct(162, 222, 56, 14, 97, 0, 1, 86400); - this.AddPackage(configuration, 203, "Scroll Package D", 488, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) + this.AddPackage(configuration, 203, LocalizedString.FromResource(() => CashShopPackageNames.ScrollPackageD), 488, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: true) .AddProduct(156, 216, 56, 14, 77, 0, 1, 86400) .AddProduct(157, 217, 56, 14, 76, 0, 1, 86400) .AddProduct(158, 218, 120, 14, 75, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400) .AddProduct(162, 222, 56, 14, 97, 0, 1, 86400); - this.AddPackage(configuration, 90, "Scroll of Protection", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 90, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofProtection), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(26, 43, 100, 14, 73, 0, 1, 86400) .AddProduct(26, 44, 500, 14, 73, 0, 1, 604800); - this.AddPackage(configuration, 92, "Scroll of Quickness", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 92, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofQuickness), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(25, 41, 150, 14, 72, 0, 1, 86400) .AddProduct(25, 42, 700, 14, 72, 0, 1, 604800); - this.AddPackage(configuration, 88, "Scroll of Wrath", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 88, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofWrath), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(27, 45, 150, 14, 74, 0, 1, 86400) .AddProduct(27, 46, 700, 14, 74, 0, 1, 604800); - this.AddPackage(configuration, 86, "Scroll of Wizardry", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 86, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofWizardry), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(28, 47, 150, 14, 75, 0, 1, 86400) .AddProduct(28, 48, 700, 14, 75, 0, 1, 604800); - this.AddPackage(configuration, 76, "Scroll of Strengthener", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 76, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofStrengthener), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(37, 60, 150, 14, 98, 0, 1, 86400) .AddProduct(37, 61, 700, 14, 98, 0, 1, 604800); - this.AddPackage(configuration, 78, "Scroll of Battle", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 78, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofBattle), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(36, 58, 150, 14, 97, 0, 1, 86400) .AddProduct(36, 59, 700, 14, 97, 0, 1, 604800); - this.AddPackage(configuration, 82, "Scroll of Mana", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 82, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofMana), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(30, 51, 100, 14, 77, 0, 1, 86400) .AddProduct(30, 52, 500, 14, 77, 0, 1, 604800); - this.AddPackage(configuration, 84, "Scroll of Health", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 84, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofHealth), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(29, 49, 100, 14, 76, 0, 1, 86400) .AddProduct(29, 50, 500, 14, 76, 0, 1, 604800); - this.AddPackage(configuration, 30, "Pet Panda", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 30, LocalizedString.FromResource(() => CashShopPackageNames.PetPanda), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(60, 99, 150, 13, 80, 0, 1, 86400) .AddProduct(60, 100, 700, 13, 80, 0, 1, 604800); - this.AddPackage(configuration, 28, "Pet Skeleton", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 28, LocalizedString.FromResource(() => CashShopPackageNames.PetSkeleton), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(61, 101, 150, 13, 123, 0, 1, 86400) .AddProduct(61, 102, 700, 13, 123, 0, 1, 604800); - this.AddPackage(configuration, 10, "Pet Unicorn", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 10, LocalizedString.FromResource(() => CashShopPackageNames.PetUnicorn), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(72, 121, 150, 13, 106, 0, 1, 86400) .AddProduct(72, 122, 700, 13, 106, 0, 1, 604800); - this.AddPackage(configuration, 102, "Demon", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 102, LocalizedString.FromResource(() => CashShopPackageNames.Demon), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(20, 31, 100, 13, 64, 0, 1, 86400) .AddProduct(20, 32, 500, 13, 64, 0, 1, 604800) .AddProduct(20, 33, 1400, 13, 64, 0, 1, 2592000); - this.AddPackage(configuration, 100, "Spirit of Guardian", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 100, LocalizedString.FromResource(() => CashShopPackageNames.SpiritofGuardian), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(21, 34, 100, 13, 65, 0, 1, 86400) .AddProduct(21, 35, 500, 13, 65, 0, 1, 604800) .AddProduct(21, 36, 1400, 13, 65, 0, 1, 2592000); - this.AddPackage(configuration, 36, "Panda Ring", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 36, LocalizedString.FromResource(() => CashShopPackageNames.PandaRing), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(57, 93, 100, 13, 76, 0, 1, 86400) .AddProduct(57, 94, 500, 13, 76, 0, 1, 604800); - this.AddPackage(configuration, 32, "Skeleton Transformation Ring", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 32, LocalizedString.FromResource(() => CashShopPackageNames.SkeletonTransformationRing), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(59, 97, 100, 13, 122, 0, 1, 86400) .AddProduct(59, 98, 500, 13, 122, 0, 1, 604800); - this.AddPackage(configuration, 34, "Wizard Ring", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 34, LocalizedString.FromResource(() => CashShopPackageNames.WizardRing), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(58, 95, 100, 13, 20, 0, 1, 86400) .AddProduct(58, 96, 500, 13, 20, 0, 1, 604800); - this.AddPackage(configuration, 147, "Critical Ring of Wizard", 130, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 147, LocalizedString.FromResource(() => CashShopPackageNames.CriticalRingofWizard), 130, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(71, 119, 130, 13, 107, 0, 1, 86400) .AddProduct(71, 120, 600, 13, 107, 0, 1, 604800); - this.AddPackage(configuration, 26, "Sapphire Ring", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 26, LocalizedString.FromResource(() => CashShopPackageNames.SapphireRing), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(62, 103, 80, 13, 109, 0, 1, 86400) .AddProduct(62, 104, 400, 13, 109, 0, 1, 604800); - this.AddPackage(configuration, 24, "Ruby Ring", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 24, LocalizedString.FromResource(() => CashShopPackageNames.RubyRing), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(63, 105, 80, 13, 110, 0, 1, 86400) .AddProduct(63, 106, 400, 13, 110, 0, 1, 604800); - this.AddPackage(configuration, 22, "Topaz Ring", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 22, LocalizedString.FromResource(() => CashShopPackageNames.TopazRing), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(64, 107, 80, 13, 111, 0, 1, 86400) .AddProduct(64, 108, 400, 13, 111, 0, 1, 604800); - this.AddPackage(configuration, 20, "Amethyst Ring", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 20, LocalizedString.FromResource(() => CashShopPackageNames.AmethystRing), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(65, 109, 80, 13, 112, 0, 1, 86400) .AddProduct(65, 110, 400, 13, 112, 0, 1, 604800); - this.AddPackage(configuration, 18, "Ruby Necklace", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 18, LocalizedString.FromResource(() => CashShopPackageNames.RubyNecklace), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(66, 111, 90, 13, 113, 0, 1, 86400) .AddProduct(66, 112, 450, 13, 113, 0, 1, 604800); - this.AddPackage(configuration, 16, "Emerald Necklace", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 16, LocalizedString.FromResource(() => CashShopPackageNames.EmeraldNecklace), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(67, 113, 90, 13, 114, 0, 1, 86400) .AddProduct(67, 114, 450, 13, 114, 0, 1, 604800); - this.AddPackage(configuration, 14, "Sapphire Necklace", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 14, LocalizedString.FromResource(() => CashShopPackageNames.SapphireNecklace), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(68, 115, 90, 13, 115, 0, 1, 86400) .AddProduct(68, 116, 450, 13, 115, 0, 1, 604800); - this.AddPackage(configuration, 256, "Little Warrior's Cloak", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 256, LocalizedString.FromResource(() => CashShopPackageNames.LittleWarriorsCloak), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(283, 351, 90, 12, 135, 0, 1, 86400) .AddProduct(283, 352, 450, 12, 135, 0, 1, 604800); - this.AddPackage(configuration, 44, "Small Wings of Disaster", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 44, LocalizedString.FromResource(() => CashShopPackageNames.SmallWingsofDisaster), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(53, 85, 90, 12, 131, 0, 1, 86400) .AddProduct(53, 86, 450, 12, 131, 0, 1, 604800); - this.AddPackage(configuration, 42, "Small Wings of Fairy", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 42, LocalizedString.FromResource(() => CashShopPackageNames.SmallWingsofFairy), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(54, 87, 90, 12, 132, 0, 1, 86400) .AddProduct(54, 88, 450, 12, 132, 0, 1, 604800); - this.AddPackage(configuration, 40, "Small Wings of Heaven", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 40, LocalizedString.FromResource(() => CashShopPackageNames.SmallWingsofHeaven), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(55, 89, 90, 12, 133, 0, 1, 86400) .AddProduct(55, 90, 450, 12, 133, 0, 1, 604800); - this.AddPackage(configuration, 38, "Small Wings of Satan", 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 38, LocalizedString.FromResource(() => CashShopPackageNames.SmallWingsofSatan), 90, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(56, 91, 90, 12, 134, 0, 1, 86400) .AddProduct(56, 92, 450, 12, 134, 0, 1, 604800); - this.AddPackage(configuration, 118, "Devil Square Ticket", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 118, LocalizedString.FromResource(() => CashShopPackageNames.DevilSquareTicket), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(12, 20, 100, 13, 46, 0, 1, 0) .AddProduct(12, 21, 900, 13, 46, 0, 10, 0); - this.AddPackage(configuration, 116, "Blood Castle Ticket", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 116, LocalizedString.FromResource(() => CashShopPackageNames.BloodCastleTicket), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(13, 22, 100, 13, 47, 0, 1, 0) .AddProduct(13, 23, 900, 13, 47, 0, 10, 0); - this.AddPackage(configuration, 104, "Illusion Temple Ticket", 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 104, LocalizedString.FromResource(() => CashShopPackageNames.IllusionTempleTicket), 150, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(19, 29, 150, 13, 61, 0, 1, 0) .AddProduct(19, 30, 1350, 13, 61, 0, 10, 0); - this.AddPackage(configuration, 56, "Kalima Ticket", 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 56, LocalizedString.FromResource(() => CashShopPackageNames.KalimaTicket), 80, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(47, 73, 80, 13, 48, 0, 1, 0) .AddProduct(47, 74, 720, 13, 48, 0, 10, 0); - this.AddPackage(configuration, 3, "Open Access Ticket to Varka 7", 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 3, LocalizedString.FromResource(() => CashShopPackageNames.OpenAccessTickettoVarka7), 100, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(79, 134, 100, 13, 127, 0, 1, 0) .AddProduct(79, 135, 900, 13, 127, 0, 10, 0); - this.AddPackage(configuration, 4, "Elite SD Potion", 40, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 4, LocalizedString.FromResource(() => CashShopPackageNames.EliteSDPotion), 40, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(76, 129, 40, 14, 133, 0, 10, 0); - this.AddPackage(configuration, 96, "Elite Healing Potion", 20, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 96, LocalizedString.FromResource(() => CashShopPackageNames.EliteHealingPotion), 20, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(23, 39, 20, 14, 70, 0, 20, 0); - this.AddPackage(configuration, 94, "Elite Mana Potion", 20, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 94, LocalizedString.FromResource(() => CashShopPackageNames.EliteManaPotion), 20, CashShopCoinType.WCoinC, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(24, 40, 20, 14, 71, 0, 20, 0); - this.AddPackage(configuration, 2224, "[Normal] eX700 OBT - Celebration Package", 4500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2224, LocalizedString.FromResource(() => CashShopPackageNames.NormaleX700OBTCelebrationPackage), 4500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(1352, 1556, 1125, 13, 124, 0, 1, 2592000) .AddProduct(1353, 1557, 1125, 13, 44, 0, 1, 2592000) .AddProduct(1354, 1558, 1125, 13, 62, 0, 1, 2592000) .AddProduct(1355, 1559, 1125, 13, 80, 0, 1, 2592000); - this.AddPackage(configuration, 2223, "[Master] eX700 OBT - Celebration Package", 4500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2223, LocalizedString.FromResource(() => CashShopPackageNames.MastereX700OBTCelebrationPackage), 4500, CashShopCoinType.WCoinC, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(1352, 1556, 1125, 13, 124, 0, 1, 2592000) .AddProduct(1354, 1558, 1125, 13, 62, 0, 1, 2592000) .AddProduct(1355, 1559, 1125, 13, 80, 0, 1, 2592000) .AddProduct(1356, 1560, 1125, 13, 94, 0, 1, 2592000); - this.AddPackage(configuration, 2222, "[Master] eX700 OBT - Celebration Package", 4500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2222, LocalizedString.FromResource(() => CashShopPackageNames.MastereX700OBTCelebrationPackage), 4500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(1352, 1556, 1125, 13, 124, 0, 1, 2592000) .AddProduct(1354, 1558, 1125, 13, 62, 0, 1, 2592000) .AddProduct(1355, 1559, 1125, 13, 80, 0, 1, 2592000) .AddProduct(1356, 1560, 1125, 13, 94, 0, 1, 2592000); - this.AddPackage(configuration, 2221, "[Normal] eX700 OBT - Celebration Package", 4500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2221, LocalizedString.FromResource(() => CashShopPackageNames.NormaleX700OBTCelebrationPackage), 4500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(1352, 1556, 1125, 13, 124, 0, 1, 2592000) .AddProduct(1353, 1557, 1125, 13, 44, 0, 1, 2592000) .AddProduct(1354, 1558, 1125, 13, 62, 0, 1, 2592000) .AddProduct(1355, 1559, 1125, 13, 80, 0, 1, 2592000); - this.AddPackage(configuration, 141, "[Chaos Card Gold]", 350, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 141, LocalizedString.FromResource(() => CashShopPackageNames.BracketedChaosCardGold), 350, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(32, 54, 350, 14, 92, 0, 1, 0); - this.AddPackage(configuration, 81, "[Chaos Card Mini]", 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 81, LocalizedString.FromResource(() => CashShopPackageNames.BracketedChaosCardMini), 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(34, 56, 120, 14, 95, 0, 1, 0); - this.AddPackage(configuration, 2118, "[10+3][Chaos Card Mini]", 1200, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2118, LocalizedString.FromResource(() => CashShopPackageNames.TenPlusThreeChaosCardMini), 1200, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(546, 633, 0, 14, 95, 0, 1, 0) .AddProduct(547, 634, 0, 14, 95, 0, 1, 0) .AddProduct(548, 635, 0, 14, 95, 0, 1, 0) @@ -332,7 +333,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(556, 643, 120, 14, 95, 0, 1, 0) .AddProduct(557, 644, 120, 14, 95, 0, 1, 0) .AddProduct(558, 645, 0, 14, 95, 0, 1, 0); - this.AddPackage(configuration, 2117, "[10+3][Chaos Card Gold]", 3500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2117, LocalizedString.FromResource(() => CashShopPackageNames.TenPlusThreeChaosCardGold), 3500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(530, 612, 0, 14, 92, 0, 1, 0) .AddProduct(534, 621, 0, 14, 92, 0, 1, 0) .AddProduct(535, 622, 0, 14, 92, 0, 1, 0) @@ -346,32 +347,32 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(543, 630, 350, 14, 92, 0, 1, 0) .AddProduct(544, 631, 350, 14, 92, 0, 1, 0) .AddProduct(545, 632, 0, 14, 92, 0, 1, 0); - this.AddPackage(configuration, 2116, "[5+1][Chaos Card Gold]", 1750, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2116, LocalizedString.FromResource(() => CashShopPackageNames.FivePlusOneChaosCardGold), 1750, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(535, 622, 0, 14, 92, 0, 1, 0) .AddProduct(541, 628, 350, 14, 92, 0, 1, 0) .AddProduct(542, 629, 350, 14, 92, 0, 1, 0) .AddProduct(543, 630, 350, 14, 92, 0, 1, 0) .AddProduct(544, 631, 350, 14, 92, 0, 1, 0) .AddProduct(545, 632, 0, 14, 92, 0, 1, 0); - this.AddPackage(configuration, 2115, "[5+1][Chaos Card Mini]", 600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2115, LocalizedString.FromResource(() => CashShopPackageNames.FivePlusOneChaosCardMini), 600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(548, 635, 0, 14, 95, 0, 1, 0) .AddProduct(554, 641, 120, 14, 95, 0, 1, 0) .AddProduct(555, 642, 120, 14, 95, 0, 1, 0) .AddProduct(556, 643, 120, 14, 95, 0, 1, 0) .AddProduct(557, 644, 120, 14, 95, 0, 1, 0) .AddProduct(558, 645, 0, 14, 95, 0, 1, 0); - this.AddPackage(configuration, 412, "[Gold Channel Ticket]", 190, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 412, LocalizedString.FromResource(() => CashShopPackageNames.BracketedGoldChannelTicket), 190, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(528, 607, 190, 13, 124, 0, 1, 86400) .AddProduct(528, 608, 400, 13, 124, 0, 1, 259200) .AddProduct(528, 609, 800, 13, 124, 0, 1, 604800) .AddProduct(528, 610, 2300, 13, 124, 0, 1, 2592000); - this.AddPackage(configuration, 424, "[+GP][Gold Channel Ticket_7 Day]", 800, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 424, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPGoldChannelTicket7Day), 800, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(512, 591, 0, 14, 120, 0, 1, 0) .AddProduct(526, 605, 800, 13, 124, 0, 1, 604800); - this.AddPackage(configuration, 422, "[+GP][Gold Channel Ticket_30 Day]", 2300, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 422, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPGoldChannelTicket30Day), 2300, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(517, 596, 0, 14, 120, 0, 1, 0) .AddProduct(527, 606, 2300, 13, 124, 0, 1, 2592000); - this.AddPackage(configuration, 344, "[Skill book package for Magic Gladiator]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 344, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforMagicGladiator), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -380,7 +381,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(455, 524, 200, 15, 29, 0, 1, 0) .AddProduct(456, 525, 150, 15, 12, 0, 1, 0) .AddProduct(457, 526, 150, 12, 47, 0, 1, 0); - this.AddPackage(configuration, 343, "[Skill book package for Fairy Elf]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 343, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforFairyElf), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -389,7 +390,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(452, 521, 200, 12, 18, 0, 1, 0) .AddProduct(453, 522, 150, 12, 17, 0, 1, 0) .AddProduct(454, 523, 150, 12, 46, 0, 1, 0); - this.AddPackage(configuration, 342, "[Skill book package for Rage Fighter]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 342, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforRageFighter), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -398,7 +399,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(448, 517, 200, 15, 31, 0, 1, 0) .AddProduct(449, 518, 150, 15, 33, 0, 1, 0) .AddProduct(450, 519, 150, 15, 36, 0, 1, 0); - this.AddPackage(configuration, 341, "[Skill book package for Summoner]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 341, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforSummoner), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -407,7 +408,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(444, 513, 200, 15, 22, 0, 1, 0) .AddProduct(445, 514, 150, 15, 23, 0, 1, 0) .AddProduct(446, 515, 150, 15, 21, 0, 1, 0); - this.AddPackage(configuration, 340, "[Skill book package for Dark Wizard]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 340, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforDarkWizard), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -416,7 +417,7 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(440, 509, 200, 15, 28, 0, 1, 0) .AddProduct(441, 510, 150, 15, 18, 0, 1, 0) .AddProduct(442, 511, 150, 15, 15, 0, 1, 0); - this.AddPackage(configuration, 338, "[Skill book package for Dark Knight]", 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 338, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkillbookpackageforDarkKnight), 1500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(431, 500, 200, 13, 80, 0, 1, 604800) .AddProduct(432, 501, 600, 13, 62, 0, 1, 604800) .AddProduct(433, 502, 200, 12, 30, 0, 1, 0) @@ -425,25 +426,25 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(436, 505, 200, 12, 12, 0, 1, 0) .AddProduct(437, 506, 150, 12, 19, 0, 1, 0) .AddProduct(438, 507, 150, 12, 14, 0, 1, 0); - this.AddPackage(configuration, 261, "[Magic Backpack]", 690, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 261, LocalizedString.FromResource(() => CashShopPackageNames.BracketedMagicBackpack), 690, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(281, 349, 690, 14, 162, 0, 1, 0); - this.AddPackage(configuration, 259, "[Vault Expansion Certificate]", 2490, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 259, LocalizedString.FromResource(() => CashShopPackageNames.BracketedVaultExpansionCertificate), 2490, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(282, 350, 2490, 14, 163, 0, 1, 0); - this.AddPackage(configuration, 146, "[Level up (Master)]", 1570, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 146, LocalizedString.FromResource(() => CashShopPackageNames.BracketedLevelupMaster), 1570, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(95, 153, 700, 13, 94, 0, 1, 604800) .AddProduct(96, 154, 80, 14, 92, 0, 1, 0) .AddProduct(97, 155, 30, 14, 73, 0, 1, 86400) .AddProduct(98, 156, 600, 13, 124, 0, 1, 604800) .AddProduct(99, 157, 80, 14, 92, 0, 1, 0) .AddProduct(100, 158, 80, 14, 92, 0, 1, 0); - this.AddPackage(configuration, 144, "[Level up (normal)]", 1570, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 144, LocalizedString.FromResource(() => CashShopPackageNames.BracketedLevelupnormal), 1570, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(94, 152, 700, 13, 44, 0, 1, 604800) .AddProduct(96, 154, 80, 14, 92, 0, 1, 0) .AddProduct(97, 155, 30, 14, 73, 0, 1, 86400) .AddProduct(98, 156, 600, 13, 124, 0, 1, 604800) .AddProduct(99, 157, 80, 14, 92, 0, 1, 0) .AddProduct(100, 158, 80, 14, 92, 0, 1, 0); - this.AddPackage(configuration, 163, "[Gladiator Package]", 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 163, LocalizedString.FromResource(() => CashShopPackageNames.BracketedGladiatorPackage), 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(115, 174, 0, 14, 72, 0, 1, 86400) .AddProduct(116, 175, 0, 14, 133, 0, 10, 0) .AddProduct(118, 177, 130, 13, 107, 0, 1, 86400) @@ -451,318 +452,318 @@ private void AddPackages(CashShopConfiguration configuration) .AddProduct(120, 179, 150, 14, 98, 0, 1, 86400) .AddProduct(121, 180, 120, 13, 105, 0, 1, 86400) .AddProduct(122, 181, 0, 13, 113, 0, 1, 86400); - this.AddPackage(configuration, 13, "[Silver Key]", 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 13, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSilverKey), 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(69, 117, 20, 14, 112, 0, 1, 0); - this.AddPackage(configuration, 12, "[Gold Key]", 60, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 12, LocalizedString.FromResource(() => CashShopPackageNames.BracketedGoldKey), 60, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(70, 118, 60, 14, 113, 0, 1, 0); - this.AddPackage(configuration, 99, "[Talisman of Luck]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 99, LocalizedString.FromResource(() => CashShopPackageNames.BracketedTalismanofLuck), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(22, 37, 100, 14, 53, 0, 1, 0) .AddProduct(22, 38, 400, 14, 53, 0, 1, 0); - this.AddPackage(configuration, 264, "[Rage Fighter Character Card]", 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 264, LocalizedString.FromResource(() => CashShopPackageNames.BracketedRageFighterCharacterCard), 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(284, 353, 500, 14, 169, 0, 1, 0); - this.AddPackage(configuration, 127, "[Summoner Character Card]", 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 127, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSummonerCharacterCard), 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(31, 53, 500, 14, 91, 0, 1, 0); - this.AddPackage(configuration, 115, "[Reset Fruit Strength]", 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 115, LocalizedString.FromResource(() => CashShopPackageNames.BracketedResetFruitStrength), 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(14, 24, 250, 13, 54, 0, 1, 0); - this.AddPackage(configuration, 113, "[Reset Fruit Quickness]", 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 113, LocalizedString.FromResource(() => CashShopPackageNames.BracketedResetFruitQuickness), 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(15, 25, 250, 13, 55, 0, 1, 0); - this.AddPackage(configuration, 111, "[Reset Fruit Health]", 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 111, LocalizedString.FromResource(() => CashShopPackageNames.BracketedResetFruitHealth), 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(16, 26, 250, 13, 56, 0, 1, 0); - this.AddPackage(configuration, 109, "[Reset Fruit Energy]", 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 109, LocalizedString.FromResource(() => CashShopPackageNames.BracketedResetFruitEnergy), 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(17, 27, 250, 13, 57, 0, 1, 0); - this.AddPackage(configuration, 107, "[Reset Fruit Control]", 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 107, LocalizedString.FromResource(() => CashShopPackageNames.BracketedResetFruitControl), 250, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(18, 28, 250, 13, 58, 0, 1, 0); - this.AddPackage(configuration, 2052, "[Blue] Gold Channel Package", 600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2052, LocalizedString.FromResource(() => CashShopPackageNames.BlueGoldChannelPackage), 600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(912, 1113, 600, 13, 124, 0, 1, 2592000) .AddProduct(913, 1114, 480, 13, 124, 0, 1, 604800); - this.AddPackage(configuration, 71, "[Talisman of Resurrection]", 50, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 71, LocalizedString.FromResource(() => CashShopPackageNames.BracketedTalismanofResurrection), 50, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(40, 66, 50, 13, 69, 0, 1, 0); - this.AddPackage(configuration, 69, "[Talisman of Mobility]", 40, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 69, LocalizedString.FromResource(() => CashShopPackageNames.BracketedTalismanofMobility), 40, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(41, 67, 40, 13, 70, 0, 1, 0); - this.AddPackage(configuration, 440, "[+GP][Seal of Wealth_7 Day]", 700, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 440, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPSealofWealth7Day), 700, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(511, 590, 0, 14, 120, 0, 1, 0) .AddProduct(518, 597, 700, 13, 44, 0, 1, 604800); - this.AddPackage(configuration, 438, "[+GP][Seal of Wealth_30 Day]", 2100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 438, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPSealofWealth30Day), 2100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(516, 595, 0, 14, 120, 0, 1, 0) .AddProduct(519, 598, 2100, 13, 44, 0, 1, 2592000); - this.AddPackage(configuration, 436, "[+GP][Master Seal of Wealth_7 Day]", 700, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 436, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPMasterSealofWealth7Day), 700, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(511, 590, 0, 14, 120, 0, 1, 0) .AddProduct(520, 599, 700, 13, 94, 0, 1, 604800); - this.AddPackage(configuration, 434, "[+GP][Master Seal of Wealth_30 Day]", 2100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 434, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPMasterSealofWealth30Day), 2100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(516, 595, 0, 14, 120, 0, 1, 0) .AddProduct(521, 600, 2100, 13, 94, 0, 1, 2592000); - this.AddPackage(configuration, 432, "[+GP][Seal of Ascension_7 Day]", 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 432, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPSealofAscension7Day), 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(509, 588, 0, 14, 120, 0, 1, 0) .AddProduct(522, 601, 500, 13, 43, 0, 1, 604800); - this.AddPackage(configuration, 430, "[+GP][Seal of Ascension_30 Day]", 1400, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 430, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPSealofAscension30Day), 1400, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(514, 593, 0, 14, 120, 0, 1, 0) .AddProduct(529, 611, 1400, 13, 43, 0, 1, 2592000); - this.AddPackage(configuration, 428, "[+GP][Master Seal of Ascension_7 Day]", 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 428, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPMasterSealofAscension7Day), 500, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(509, 588, 0, 14, 120, 0, 1, 0) .AddProduct(524, 603, 500, 13, 93, 0, 1, 604800); - this.AddPackage(configuration, 426, "[+GP][Master Seal of Ascension_30 Day]", 1400, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 426, LocalizedString.FromResource(() => CashShopPackageNames.BonusGPMasterSealofAscension30Day), 1400, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(514, 593, 0, 14, 120, 0, 1, 0) .AddProduct(525, 604, 1400, 13, 93, 0, 1, 2592000); - this.AddPackage(configuration, 123, "[Seal of Wealth]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 123, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSealofWealth), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(10, 13, 150, 13, 44, 0, 1, 86400) .AddProduct(10, 14, 350, 13, 44, 0, 1, 259200) .AddProduct(10, 15, 700, 13, 44, 0, 1, 604800) .AddProduct(10, 16, 2100, 13, 44, 0, 1, 2592000); - this.AddPackage(configuration, 125, "[Seal of Ascension]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 125, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSealofAscension), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(9, 9, 100, 13, 43, 0, 1, 86400) .AddProduct(9, 10, 250, 13, 43, 0, 1, 259200) .AddProduct(9, 11, 500, 13, 43, 0, 1, 604800) .AddProduct(9, 12, 1400, 13, 43, 0, 1, 2592000); - this.AddPackage(configuration, 49, "[Master Seal of Wealth]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 49, LocalizedString.FromResource(() => CashShopPackageNames.BracketedMasterSealofWealth), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(51, 80, 150, 13, 94, 0, 1, 86400) .AddProduct(51, 81, 700, 13, 94, 0, 1, 604800) .AddProduct(51, 82, 2100, 13, 94, 0, 1, 2592000); - this.AddPackage(configuration, 51, "[Master Seal of Ascension]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 51, LocalizedString.FromResource(() => CashShopPackageNames.BracketedMasterSealofAscension), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(50, 77, 100, 13, 93, 0, 1, 86400) .AddProduct(50, 78, 500, 13, 93, 0, 1, 604800) .AddProduct(50, 79, 1400, 13, 93, 0, 1, 2592000); - this.AddPackage(configuration, 121, "[Seal of Sustenance]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 121, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSealofSustenance), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(11, 17, 80, 13, 45, 0, 1, 86400) .AddProduct(11, 18, 680, 13, 45, 0, 1, 864000) .AddProduct(11, 19, 1250, 13, 45, 0, 1, 2592000); - this.AddPackage(configuration, 75, "[Seal of Healing]", 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 75, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSealofHealing), 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(38, 62, 120, 13, 62, 0, 1, 86400) .AddProduct(38, 63, 600, 13, 62, 0, 1, 604800); - this.AddPackage(configuration, 73, "[Seal of Divinity]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 73, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSealofDivinity), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(39, 64, 100, 13, 63, 0, 1, 86400) .AddProduct(39, 65, 500, 13, 63, 0, 1, 604800); - this.AddPackage(configuration, 8, "[AG Boost Aura]", 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 8, LocalizedString.FromResource(() => CashShopPackageNames.BracketedAGBoostAura), 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(73, 123, 120, 13, 104, 0, 1, 86400) .AddProduct(73, 124, 600, 13, 104, 0, 1, 604800); - this.AddPackage(configuration, 7, "[SD Boost Aura]", 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 7, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSDBoostAura), 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(74, 125, 120, 13, 105, 0, 1, 86400) .AddProduct(74, 126, 600, 13, 105, 0, 1, 604800); - this.AddPackage(configuration, 357, "[Worn Horseshoe]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 357, LocalizedString.FromResource(() => CashShopPackageNames.BracketedWornHorseshoe), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(463, 540, 80, 13, 134, 0, 1, 86400) .AddProduct(463, 541, 400, 13, 134, 0, 1, 604800) .AddProduct(463, 542, 1200, 13, 134, 0, 1, 2592000); - this.AddPackage(configuration, 355, "[Golden Oak Charm]", 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 355, LocalizedString.FromResource(() => CashShopPackageNames.BracketedGoldenOakCharm), 120, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(462, 537, 120, 13, 132, 0, 1, 86400) .AddProduct(462, 538, 600, 13, 132, 0, 1, 604800) .AddProduct(462, 539, 1800, 13, 132, 0, 1, 2592000); - this.AddPackage(configuration, 353, "[Oak Charm]", 30, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 353, LocalizedString.FromResource(() => CashShopPackageNames.BracketedOakCharm), 30, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(461, 534, 30, 13, 130, 0, 1, 86400) .AddProduct(461, 535, 150, 13, 130, 0, 1, 604800) .AddProduct(461, 536, 500, 13, 130, 0, 1, 2592000); - this.AddPackage(configuration, 349, "[Statue of Hawk]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 349, LocalizedString.FromResource(() => CashShopPackageNames.BracketedStatueofHawk), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(459, 528, 80, 13, 128, 0, 1, 86400) .AddProduct(459, 529, 400, 13, 128, 0, 1, 604800) .AddProduct(459, 530, 1200, 13, 128, 0, 1, 2592000); - this.AddPackage(configuration, 351, "[Statue of Goral]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 351, LocalizedString.FromResource(() => CashShopPackageNames.BracketedStatueofGoral), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(460, 531, 80, 13, 129, 0, 1, 86400) .AddProduct(460, 532, 400, 13, 129, 0, 1, 604800) .AddProduct(460, 533, 1200, 13, 129, 0, 1, 2592000); - this.AddPackage(configuration, 196, "[Scroll Package A]", 320, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 196, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollPackageA), 320, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(159, 219, 120, 14, 74, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400); - this.AddPackage(configuration, 198, "[Scroll Package B]", 320, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 198, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollPackageB), 320, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(158, 218, 120, 14, 75, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400); - this.AddPackage(configuration, 200, "[Scroll Package C]", 488, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 200, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollPackageC), 488, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(156, 216, 56, 14, 77, 0, 1, 86400) .AddProduct(157, 217, 56, 14, 76, 0, 1, 86400) .AddProduct(159, 219, 120, 14, 74, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400) .AddProduct(162, 222, 56, 14, 97, 0, 1, 86400); - this.AddPackage(configuration, 202, "[Scroll Package D]", 488, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 202, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollPackageD), 488, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(156, 216, 56, 14, 77, 0, 1, 86400) .AddProduct(157, 217, 56, 14, 76, 0, 1, 86400) .AddProduct(158, 218, 120, 14, 75, 0, 1, 86400) .AddProduct(160, 220, 100, 14, 73, 0, 1, 86400) .AddProduct(161, 221, 100, 14, 72, 0, 1, 86400) .AddProduct(162, 222, 56, 14, 97, 0, 1, 86400); - this.AddPackage(configuration, 91, "[Scroll of Protection]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 91, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofProtection), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(26, 43, 100, 14, 73, 0, 1, 86400) .AddProduct(26, 44, 500, 14, 73, 0, 1, 604800); - this.AddPackage(configuration, 93, "[Scroll of Quickness]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 93, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofQuickness), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(25, 41, 150, 14, 72, 0, 1, 86400) .AddProduct(25, 42, 700, 14, 72, 0, 1, 604800); - this.AddPackage(configuration, 89, "[Scroll of Wrath]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 89, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofWrath), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(27, 45, 150, 14, 74, 0, 1, 86400) .AddProduct(27, 46, 700, 14, 74, 0, 1, 604800); - this.AddPackage(configuration, 87, "[Scroll of Wizardry]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 87, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofWizardry), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(28, 47, 150, 14, 75, 0, 1, 86400) .AddProduct(28, 48, 700, 14, 75, 0, 1, 604800); - this.AddPackage(configuration, 77, "[Scroll of Strengthener]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 77, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofStrengthener), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(37, 60, 150, 14, 98, 0, 1, 86400) .AddProduct(37, 61, 700, 14, 98, 0, 1, 604800); - this.AddPackage(configuration, 79, "[Scroll of Battle]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 79, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofBattle), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(36, 58, 150, 14, 97, 0, 1, 86400) .AddProduct(36, 59, 700, 14, 97, 0, 1, 604800); - this.AddPackage(configuration, 83, "[Scroll of Mana]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 83, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofMana), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(30, 51, 100, 14, 77, 0, 1, 86400) .AddProduct(30, 52, 500, 14, 77, 0, 1, 604800); - this.AddPackage(configuration, 85, "[Scroll of Health]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 85, LocalizedString.FromResource(() => CashShopPackageNames.BracketedScrollofHealth), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(29, 49, 100, 14, 76, 0, 1, 86400) .AddProduct(29, 50, 500, 14, 76, 0, 1, 604800); - this.AddPackage(configuration, 31, "[Pet Panda]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 31, LocalizedString.FromResource(() => CashShopPackageNames.BracketedPetPanda), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(60, 99, 150, 13, 80, 0, 1, 86400) .AddProduct(60, 100, 700, 13, 80, 0, 1, 604800); - this.AddPackage(configuration, 29, "[Pet Skeleton]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 29, LocalizedString.FromResource(() => CashShopPackageNames.BracketedPetSkeleton), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(61, 101, 150, 13, 123, 0, 1, 86400) .AddProduct(61, 102, 700, 13, 123, 0, 1, 604800); - this.AddPackage(configuration, 11, "[Pet Unicorn]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 11, LocalizedString.FromResource(() => CashShopPackageNames.BracketedPetUnicorn), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(72, 121, 150, 13, 106, 0, 1, 86400) .AddProduct(72, 122, 700, 13, 106, 0, 1, 604800); - this.AddPackage(configuration, 103, "[Demon]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 103, LocalizedString.FromResource(() => CashShopPackageNames.BracketedDemon), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(20, 31, 100, 13, 64, 0, 1, 86400) .AddProduct(20, 32, 500, 13, 64, 0, 1, 604800) .AddProduct(20, 33, 1400, 13, 64, 0, 1, 2592000); - this.AddPackage(configuration, 101, "[Spirit of Guardian]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 101, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSpiritofGuardian), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(21, 34, 100, 13, 65, 0, 1, 86400) .AddProduct(21, 35, 500, 13, 65, 0, 1, 604800) .AddProduct(21, 36, 1400, 13, 65, 0, 1, 2592000); - this.AddPackage(configuration, 37, "[Panda Ring]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 37, LocalizedString.FromResource(() => CashShopPackageNames.BracketedPandaRing), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(57, 93, 100, 13, 76, 0, 1, 86400) .AddProduct(57, 94, 500, 13, 76, 0, 1, 604800); - this.AddPackage(configuration, 33, "[Skeleton Transformation Ring]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 33, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSkeletonTransformationRing), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(59, 97, 100, 13, 122, 0, 1, 86400) .AddProduct(59, 98, 500, 13, 122, 0, 1, 604800); - this.AddPackage(configuration, 35, "[Wizard Ring]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 35, LocalizedString.FromResource(() => CashShopPackageNames.BracketedWizardRing), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(58, 95, 100, 13, 20, 0, 1, 86400) .AddProduct(58, 96, 500, 13, 20, 0, 1, 604800); - this.AddPackage(configuration, 148, "[Critical Ring of Wizard]", 130, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 148, LocalizedString.FromResource(() => CashShopPackageNames.BracketedCriticalRingofWizard), 130, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(71, 119, 130, 13, 107, 0, 1, 86400) .AddProduct(71, 120, 600, 13, 107, 0, 1, 604800); - this.AddPackage(configuration, 27, "[Sapphire Ring]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 27, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSapphireRing), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(62, 103, 80, 13, 109, 0, 1, 86400) .AddProduct(62, 104, 400, 13, 109, 0, 1, 604800); - this.AddPackage(configuration, 25, "[Ruby Ring]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 25, LocalizedString.FromResource(() => CashShopPackageNames.BracketedRubyRing), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(63, 105, 80, 13, 110, 0, 1, 86400) .AddProduct(63, 106, 400, 13, 110, 0, 1, 604800); - this.AddPackage(configuration, 23, "[Topaz Ring]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 23, LocalizedString.FromResource(() => CashShopPackageNames.BracketedTopazRing), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(64, 107, 80, 13, 111, 0, 1, 86400) .AddProduct(64, 108, 400, 13, 111, 0, 1, 604800); - this.AddPackage(configuration, 21, "[Amethyst Ring]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 21, LocalizedString.FromResource(() => CashShopPackageNames.BracketedAmethystRing), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(65, 109, 80, 13, 112, 0, 1, 86400) .AddProduct(65, 110, 400, 13, 112, 0, 1, 604800); - this.AddPackage(configuration, 19, "[Ruby Necklace]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 19, LocalizedString.FromResource(() => CashShopPackageNames.BracketedRubyNecklace), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(66, 111, 90, 13, 113, 0, 1, 86400) .AddProduct(66, 112, 450, 13, 113, 0, 1, 604800); - this.AddPackage(configuration, 17, "[Emerald Necklace]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 17, LocalizedString.FromResource(() => CashShopPackageNames.BracketedEmeraldNecklace), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(67, 113, 90, 13, 114, 0, 1, 86400) .AddProduct(67, 114, 450, 13, 114, 0, 1, 604800); - this.AddPackage(configuration, 15, "[Sapphire Necklace]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 15, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSapphireNecklace), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(68, 115, 90, 13, 115, 0, 1, 86400) .AddProduct(68, 116, 450, 13, 115, 0, 1, 604800); - this.AddPackage(configuration, 257, "[Little Warrior's Cloak]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 257, LocalizedString.FromResource(() => CashShopPackageNames.BracketedLittleWarriorsCloak), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(283, 351, 90, 12, 135, 0, 1, 86400) .AddProduct(283, 352, 450, 12, 135, 0, 1, 604800); - this.AddPackage(configuration, 45, "[Small Wings of Disaster]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 45, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSmallWingsofDisaster), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(53, 85, 90, 12, 131, 0, 1, 86400) .AddProduct(53, 86, 450, 12, 131, 0, 1, 604800); - this.AddPackage(configuration, 43, "[Small Wings of Fairy]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 43, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSmallWingsofFairy), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(54, 87, 90, 12, 132, 0, 1, 86400) .AddProduct(54, 88, 450, 12, 132, 0, 1, 604800); - this.AddPackage(configuration, 41, "[Small Wings of Heaven]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 41, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSmallWingsofHeaven), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(55, 89, 90, 12, 133, 0, 1, 86400) .AddProduct(55, 90, 450, 12, 133, 0, 1, 604800); - this.AddPackage(configuration, 39, "[Small Wings of Satan]", 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 39, LocalizedString.FromResource(() => CashShopPackageNames.BracketedSmallWingsofSatan), 90, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(56, 91, 90, 12, 134, 0, 1, 86400) .AddProduct(56, 92, 450, 12, 134, 0, 1, 604800); - this.AddPackage(configuration, 2051, "[Platinum] Gold Channel Package", 1600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) + this.AddPackage(configuration, 2051, LocalizedString.FromResource(() => CashShopPackageNames.PlatinumGoldChannelPackage), 1600, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: true) .AddProduct(914, 1115, 480, 13, 124, 0, 1, 1296000) .AddProduct(915, 1116, 1600, 13, 124, 0, 1, 2592000); - this.AddPackage(configuration, 360, "1st Lucky Armor Ticket", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 360, LocalizedString.FromResource(() => CashShopPackageNames.FirstLuckyArmorTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(465, 544, 100, 13, 135, 0, 1, 0); - this.AddPackage(configuration, 361, "1st Lucky Pants Ticket", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 361, LocalizedString.FromResource(() => CashShopPackageNames.FirstLuckyPantsTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(466, 545, 100, 13, 136, 0, 1, 0); - this.AddPackage(configuration, 362, "1st Lucky Helm Ticket", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 362, LocalizedString.FromResource(() => CashShopPackageNames.FirstLuckyHelmTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(467, 546, 100, 13, 137, 0, 1, 0); - this.AddPackage(configuration, 363, "1st Lucky Gloves Ticket", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 363, LocalizedString.FromResource(() => CashShopPackageNames.FirstLuckyGlovesTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(468, 547, 100, 13, 138, 0, 1, 0); - this.AddPackage(configuration, 364, "1st Lucky Boots Ticket", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 364, LocalizedString.FromResource(() => CashShopPackageNames.FirstLuckyBootsTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(469, 548, 100, 13, 139, 0, 1, 0); - this.AddPackage(configuration, 365, "2nd Lucky Armor Ticket", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 365, LocalizedString.FromResource(() => CashShopPackageNames.SecondLuckyArmorTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(470, 549, 150, 13, 140, 0, 1, 0); - this.AddPackage(configuration, 366, "2nd Lucky Pants Ticket", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 366, LocalizedString.FromResource(() => CashShopPackageNames.SecondLuckyPantsTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(471, 550, 150, 13, 141, 0, 1, 0); - this.AddPackage(configuration, 367, "2nd Lucky Helm Ticket", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 367, LocalizedString.FromResource(() => CashShopPackageNames.SecondLuckyHelmTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(472, 551, 150, 13, 142, 0, 1, 0); - this.AddPackage(configuration, 368, "2nd Lucky Gloves Ticket", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 368, LocalizedString.FromResource(() => CashShopPackageNames.SecondLuckyGlovesTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(473, 552, 150, 13, 143, 0, 1, 0); - this.AddPackage(configuration, 369, "2nd Lucky Boots Ticket", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 369, LocalizedString.FromResource(() => CashShopPackageNames.SecondLuckyBootsTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(474, 553, 150, 13, 144, 0, 1, 0); - this.AddPackage(configuration, 119, "[Devil Square Ticket]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 119, LocalizedString.FromResource(() => CashShopPackageNames.BracketedDevilSquareTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(12, 20, 100, 13, 46, 0, 1, 0) .AddProduct(12, 21, 900, 13, 46, 0, 10, 0); - this.AddPackage(configuration, 117, "[Blood Castle Ticket]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 117, LocalizedString.FromResource(() => CashShopPackageNames.BracketedBloodCastleTicket), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(13, 22, 100, 13, 47, 0, 1, 0) .AddProduct(13, 23, 900, 13, 47, 0, 10, 0); - this.AddPackage(configuration, 105, "[Illusion Temple Ticket]", 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 105, LocalizedString.FromResource(() => CashShopPackageNames.BracketedIllusionTempleTicket), 150, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(19, 29, 150, 13, 61, 0, 1, 0) .AddProduct(19, 30, 1350, 13, 61, 0, 10, 0); - this.AddPackage(configuration, 57, "[Kalima Ticket]", 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 57, LocalizedString.FromResource(() => CashShopPackageNames.BracketedKalimaTicket), 80, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(47, 73, 80, 13, 48, 0, 1, 0) .AddProduct(47, 74, 720, 13, 48, 0, 10, 0); - this.AddPackage(configuration, 149, "[Open Access Ticket to Varka 7]", 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 149, LocalizedString.FromResource(() => CashShopPackageNames.BracketedOpenAccessTickettoVarka7), 100, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(79, 134, 100, 13, 127, 0, 1, 0) .AddProduct(79, 135, 900, 13, 127, 0, 10, 0); - this.AddPackage(configuration, 5, "[Elite SD Potion]", 40, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 5, LocalizedString.FromResource(() => CashShopPackageNames.BracketedEliteSDPotion), 40, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(76, 129, 40, 14, 133, 0, 10, 0); - this.AddPackage(configuration, 97, "[Elite Healing Potion]", 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 97, LocalizedString.FromResource(() => CashShopPackageNames.BracketedEliteHealingPotion), 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(23, 39, 20, 14, 70, 0, 20, 0); - this.AddPackage(configuration, 95, "[Elite Mana Potion]", 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 95, LocalizedString.FromResource(() => CashShopPackageNames.BracketedEliteManaPotion), 20, CashShopCoinType.WCoinP, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(24, 40, 20, 14, 71, 0, 20, 0); - this.AddPackage(configuration, 385, "Bundle of Jewel of Soul (30)", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 385, LocalizedString.FromResource(() => CashShopPackageNames.BundleofJewelofSoul30), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(500, 579, 2000, 12, 31, 2, 1, 0); - this.AddPackage(configuration, 384, "Bundle of Jewel of Bless (30)", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 384, LocalizedString.FromResource(() => CashShopPackageNames.BundleofJewelofBless30), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(499, 578, 2000, 12, 30, 2, 1, 0); - this.AddPackage(configuration, 386, "Jewel of Chaos Bundle (10)", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 386, LocalizedString.FromResource(() => CashShopPackageNames.JewelofChaosBundle10), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(501, 580, 2000, 12, 141, 0, 1, 0); - this.AddPackage(configuration, 387, "Jewel of Life Bundle (10)", 4800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 387, LocalizedString.FromResource(() => CashShopPackageNames.JewelofLifeBundle10), 4800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(502, 581, 4800, 12, 136, 0, 1, 0); - this.AddPackage(configuration, 388, "Bundle of Jewel of Harmony (10)", 4800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 388, LocalizedString.FromResource(() => CashShopPackageNames.BundleofJewelofHarmony10), 4800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(503, 582, 4800, 12, 140, 0, 1, 0); - this.AddPackage(configuration, 389, "Talisman of Luck 10%", 3200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 389, LocalizedString.FromResource(() => CashShopPackageNames.TalismanofLuck10Percent), 3200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(504, 583, 3200, 14, 53, 0, 1, 0); - this.AddPackage(configuration, 391, "Rare Item Ticket 8", 100000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 391, LocalizedString.FromResource(() => CashShopPackageNames.RareItemTicket8), 100000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(506, 585, 100000, 14, 146, 0, 1, 0); - this.AddPackage(configuration, 390, "Rare Item Ticket 11", 60000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 390, LocalizedString.FromResource(() => CashShopPackageNames.RareItemTicket11), 60000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(505, 584, 60000, 14, 149, 0, 1, 0); - this.AddPackage(configuration, 465, "[GP]Box of kundun +5", 3200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 465, LocalizedString.FromResource(() => CashShopPackageNames.GPBoxofkundunPlus5), 3200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(563, 650, 3200, 14, 11, 12, 1, 0); - this.AddPackage(configuration, 464, "[GP]Box of kundun +4", 2400, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 464, LocalizedString.FromResource(() => CashShopPackageNames.GPBoxofkundunPlus4), 2400, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(562, 649, 2400, 14, 11, 11, 1, 0); - this.AddPackage(configuration, 463, "[GP]Box of kundun +3", 1600, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 463, LocalizedString.FromResource(() => CashShopPackageNames.GPBoxofkundunPlus3), 1600, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(561, 648, 1600, 14, 11, 10, 1, 0); - this.AddPackage(configuration, 462, "[GP]Box of kundun +2", 800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 462, LocalizedString.FromResource(() => CashShopPackageNames.GPBoxofkundunPlus2), 800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(560, 647, 800, 14, 11, 9, 1, 0); - this.AddPackage(configuration, 461, "[GP]Box of Kundun +1", 400, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) + this.AddPackage(configuration, 461, LocalizedString.FromResource(() => CashShopPackageNames.GPBoxofKundunPlus1), 400, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: false, isBundle: false) .AddProduct(559, 646, 400, 14, 11, 8, 1, 0); - this.AddPackage(configuration, 373, "Cherry Blossom Petal", 200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 373, LocalizedString.FromResource(() => CashShopPackageNames.CherryBlossomPetal), 200, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(488, 567, 200, 14, 87, 0, 1, 0); - this.AddPackage(configuration, 375, "Cherry Blossom Rice Cake", 300, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 375, LocalizedString.FromResource(() => CashShopPackageNames.CherryBlossomRiceCake), 300, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(490, 569, 300, 14, 86, 0, 1, 0); - this.AddPackage(configuration, 374, "Cherry Blossom Wine", 300, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 374, LocalizedString.FromResource(() => CashShopPackageNames.CherryBlossomWine), 300, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(489, 568, 300, 14, 85, 0, 1, 0); - this.AddPackage(configuration, 376, "Scroll of Protection_7 Day", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 376, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofProtection7Day), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(491, 570, 2000, 14, 73, 0, 1, 604800); - this.AddPackage(configuration, 378, "Scroll of Mana_7 Day", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 378, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofMana7Day), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(493, 572, 2000, 14, 77, 0, 1, 604800); - this.AddPackage(configuration, 377, "Scroll of Health_7 Day", 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 377, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofHealth7Day), 2000, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(492, 571, 2000, 14, 76, 0, 1, 604800); - this.AddPackage(configuration, 382, "Scroll of Wrath_7 Day", 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 382, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofWrath7Day), 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(497, 576, 2800, 14, 74, 0, 1, 604800); - this.AddPackage(configuration, 383, "Scroll of Wizardry_7 Day", 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 383, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofWizardry7Day), 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(498, 577, 2800, 14, 75, 0, 1, 604800); - this.AddPackage(configuration, 381, "Scroll of Quickness_7 Day", 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 381, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofQuickness7Day), 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(496, 575, 2800, 14, 72, 0, 1, 604800); - this.AddPackage(configuration, 379, "Scroll of Battle_7 Day", 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 379, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofBattle7Day), 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(494, 573, 2800, 14, 97, 0, 1, 604800); - this.AddPackage(configuration, 380, "Scroll of Strengthener_7 Day", 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) + this.AddPackage(configuration, 380, LocalizedString.FromResource(() => CashShopPackageNames.ScrollofStrengthener7Day), 2800, CashShopCoinType.GoblinPoints, isForSale: true, isGiftable: true, isBundle: false) .AddProduct(495, 574, 2800, 14, 98, 0, 1, 604800); } - private PackageBuilder AddPackage(CashShopConfiguration configuration, int packageSequence, string name, int price, CashShopCoinType coinType, bool isForSale, bool isGiftable, bool isBundle) + private PackageBuilder AddPackage(CashShopConfiguration configuration, int packageSequence, LocalizedString name, int price, CashShopCoinType coinType, bool isForSale, bool isGiftable, bool isBundle) { var package = this.Context.CreateNew(); package.PackageSequence = packageSequence; diff --git a/src/Web/AdminPanel/Pages/CashShopCatalog.razor b/src/Web/AdminPanel/Pages/CashShopCatalog.razor index 33c48db58..6dff9207a 100644 --- a/src/Web/AdminPanel/Pages/CashShopCatalog.razor +++ b/src/Web/AdminPanel/Pages/CashShopCatalog.razor @@ -67,7 +67,7 @@ else if (this._selectedPackage is not { } package)
- + @CashShopCoinCaption.Get(context.CoinType) @GetPriceText(context) @GetFlagText(context.IsForSale) @@ -102,7 +102,7 @@ else {
-

@(string.IsNullOrEmpty(package.Name) ? package.PackageSequence.ToString() : $"{package.PackageSequence}: {package.Name}")

+

@(string.IsNullOrEmpty(GetPackageName(package)) ? package.PackageSequence.ToString() : $"{package.PackageSequence}: {GetPackageName(package)}")


@foreach (var issue in CashShopCatalogCheck.GetIssues(configuration, package)) @@ -118,8 +118,7 @@ else
- - +
diff --git a/src/Web/AdminPanel/Pages/CashShopCatalog.razor.cs b/src/Web/AdminPanel/Pages/CashShopCatalog.razor.cs index e816fc518..d7c001598 100644 --- a/src/Web/AdminPanel/Pages/CashShopCatalog.razor.cs +++ b/src/Web/AdminPanel/Pages/CashShopCatalog.razor.cs @@ -4,6 +4,7 @@ namespace MUnique.OpenMU.Web.AdminPanel.Pages; +using System.Globalization; using System.Threading; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.QuickGrid; @@ -63,7 +64,8 @@ public partial class CashShopCatalog : ComponentBase, IAsyncDisposable private IQueryable? FilteredPackages => this._configuration?.Packages .Where(p => !this._onlyForSale || p.IsForSale) .Where(p => string.IsNullOrWhiteSpace(this._searchText) - || p.Name.Contains(this._searchText, StringComparison.OrdinalIgnoreCase) + || GetPackageName(p).Contains(this._searchText, StringComparison.OrdinalIgnoreCase) + || p.Name.ValueInNeutralLanguage.Contains(this._searchText, StringComparison.OrdinalIgnoreCase) || p.PackageSequence.ToString() == this._searchText.Trim()) .OrderBy(p => p.PackageSequence) .AsQueryable(); @@ -100,6 +102,8 @@ protected override async Task OnParametersSetAsync() await base.OnParametersSetAsync().ConfigureAwait(true); } + private static string GetPackageName(CashShopPackage package) => package.Name.GetTranslation(CultureInfo.CurrentUICulture) ?? string.Empty; + private static string GetItemCaption(ItemDefinition? item) { return item is null ? string.Empty : $"{item.Name} ({item.Group}, {item.Number})"; diff --git a/tests/MUnique.OpenMU.Persistence.Initialization.Tests/CashShopUpdateTest.cs b/tests/MUnique.OpenMU.Persistence.Initialization.Tests/CashShopUpdateTest.cs index 905562319..10bccac0e 100644 --- a/tests/MUnique.OpenMU.Persistence.Initialization.Tests/CashShopUpdateTest.cs +++ b/tests/MUnique.OpenMU.Persistence.Initialization.Tests/CashShopUpdateTest.cs @@ -4,7 +4,10 @@ namespace MUnique.OpenMU.Persistence.Initialization.Tests; +using System.Globalization; using Microsoft.Extensions.Logging.Abstractions; +using MUnique.OpenMU.Interfaces; +using MUnique.OpenMU.Persistence.Initialization.Captions; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.Persistence.Initialization.Updates; using MUnique.OpenMU.Persistence.InMemory; @@ -21,6 +24,85 @@ internal class CashShopUpdateTest ///
private static readonly int[] DeliveryPackages = [126, 127, 258, 259, 260, 261, 263, 264]; + /// + /// Old package names link by their script number even when database ids differ, without replacing custom names. + /// + [Test] + public async Task PackageNamesLinkAndTranslateWithoutChangingTheCatalogAsync() + { + var (context, gameConfiguration) = await CreateSeason6ConfigurationAsync().ConfigureAwait(false); + using var _ = context; + var packages = gameConfiguration.CashShopConfiguration!.Packages.ToList(); + var chinese = CultureInfo.GetCultureInfo("zh-CN"); + Assert.That(packages, Has.All.Matches(p => + p.Name.SourceKey?.StartsWith("CashShopPackageNames/", StringComparison.Ordinal) is true)); + var reference = CaptionLinkReference.Create(gameConfiguration); + var original = packages.ToDictionary(p => p.PackageSequence, p => p.Name); + var catalog = packages.Select(p => (p.PackageSequence, p.Price, p.CoinType, p.IsForSale, p.IsGiftable, p.IsBundle, Products: p.Products.ToArray())).ToArray(); + foreach (var package in packages) + { + package.SetGuid(Guid.NewGuid()); + package.Name = new LocalizedString(package.Name.ValueInNeutralLanguage); + } + + var customized = packages.Single(p => p.PackageSequence == 3); + customized.Name = "Custom ticket"; + var customTranslation = packages.Single(p => p.PackageSequence == 4); + customTranslation.Name = customTranslation.Name.WithTranslation(chinese, "自定义药水"); + var result = ConfigurationCaptions.LinkSourceKeys(gameConfiguration, reference); + Assert.That(result.Linked, Is.EqualTo(204)); + Assert.That(result.SkippedBecauseOfCustomizedNeutralText, Is.EqualTo(1)); + Assert.That(customized.Name.SourceKey, Is.Null); + Assert.That(customTranslation.Name.GetOwnTranslation(chinese), Is.EqualTo("自定义药水")); + Assert.That(packages.Single(p => p.PackageSequence == 6).Name.GetOwnTranslation(chinese), Is.Null); + var changes = ConfigurationCaptions.DetermineChanges(gameConfiguration) + .Where(change => change.CultureName == chinese.Name && change.IsRecommended).ToList(); + ConfigurationCaptions.ApplyChanges(gameConfiguration, changes.Select(change => change.Id)); + foreach (var package in packages.Where(p => p != customized && p != customTranslation)) + { + Assert.That(package.Name.GetOwnTranslation(chinese), Is.EqualTo(original[package.PackageSequence].GetOwnTranslation(chinese))); + Assert.That(package.Name.ValueInNeutralLanguage, Is.EqualTo(original[package.PackageSequence].ValueInNeutralLanguage)); + } + + Assert.That(customTranslation.Name.GetOwnTranslation(chinese), Is.EqualTo("自定义药水")); + Assert.That(ConfigurationCaptions.LinkSourceKeys(gameConfiguration, reference).Linked, Is.Zero); + Assert.That(ConfigurationCaptions.DetermineChanges(gameConfiguration).Any(change => change.CultureName == chinese.Name && change.IsRecommended), Is.False); + Assert.That(packages.Select(p => (p.PackageSequence, p.Price, p.CoinType, p.IsForSale, p.IsGiftable, p.IsBundle, Products: p.Products.ToArray())), Is.EqualTo(catalog)); + } + + /// + /// Duplicate script numbers on either side cannot identify an old package safely. + /// + /// Whether the reference rather than the target has duplicate numbers. + [TestCase(false)] + [TestCase(true)] + public void DuplicatePackageNumbersAreNotLinked(bool duplicateReference) + { + var provider = new InMemoryPersistenceContextProvider(); + using var context = provider.CreateNewContext(); + GameConfiguration CreateConfiguration(bool reference) + { + var configuration = context.CreateNew(); + configuration.CashShopConfiguration = context.CreateNew(); + for (var i = 0; i < (reference == duplicateReference ? 2 : 1); i++) + { + var package = context.CreateNew(); + package.PackageSequence = 6; + package.Name = reference + ? LocalizedString.FromResource(() => Properties.CashShopPackageNames.SDBoostAura) + : new LocalizedString("SD Boost Aura"); + configuration.CashShopConfiguration.Packages.Add(package); + } + + return configuration; + } + + var reference = CreateConfiguration(true); + var existing = CreateConfiguration(false); + Assert.That(ConfigurationCaptions.LinkSourceKeys(existing, reference).Linked, Is.Zero); + Assert.That(existing.CashShopConfiguration!.Packages, Has.All.Matches(p => p.Name.SourceKey is null)); + } + /// /// Tests that a freshly initialized database contains the cash shop configuration /// which matches the cash shop script 512.2012.084 of the game client. @@ -46,7 +128,7 @@ public async Task FreshDatabaseContainsCashShopAsync() Assert.That(configuration.Packages.Where(p => DeliveryPackages.Contains(p.PackageSequence)), Has.All.Matches(p => p.IsForSale)); var seal = configuration.Packages.Single(p => p.PackageSequence == 122); - Assert.That(seal.Name, Is.EqualTo("Seal of Wealth")); + Assert.That(seal.Name.ValueInNeutralLanguage, Is.EqualTo("Seal of Wealth")); Assert.That(seal.CoinType, Is.EqualTo(CashShopCoinType.WCoinC)); Assert.That(seal.IsBundle, Is.False); Assert.That(seal.Products.Select(p => p.Duration), Is.EquivalentTo(new[] { TimeSpan.FromDays(1), TimeSpan.FromDays(3), TimeSpan.FromDays(7), TimeSpan.FromDays(30) })); diff --git a/tests/MUnique.OpenMU.Persistence.Initialization.Tests/ConfigurationNameResourcesTests.cs b/tests/MUnique.OpenMU.Persistence.Initialization.Tests/ConfigurationNameResourcesTests.cs index 5e9522bd7..f3bae3e03 100644 --- a/tests/MUnique.OpenMU.Persistence.Initialization.Tests/ConfigurationNameResourcesTests.cs +++ b/tests/MUnique.OpenMU.Persistence.Initialization.Tests/ConfigurationNameResourcesTests.cs @@ -22,6 +22,7 @@ internal class ConfigurationNameResourcesTests private static readonly (string Name, ResourceManager ResourceManager)[] Sources = [ (nameof(CharacterClassNames), CharacterClassNames.ResourceManager), + (nameof(CashShopPackageNames), CashShopPackageNames.ResourceManager), (nameof(MapNames), MapNames.ResourceManager), (nameof(MerchantNames), MerchantNames.ResourceManager), (nameof(MonsterNames), MonsterNames.ResourceManager), diff --git a/tests/MUnique.OpenMU.Tests/CashShopPackagePersistenceTests.cs b/tests/MUnique.OpenMU.Tests/CashShopPackagePersistenceTests.cs new file mode 100644 index 000000000..8de1a433d --- /dev/null +++ b/tests/MUnique.OpenMU.Tests/CashShopPackagePersistenceTests.cs @@ -0,0 +1,40 @@ +// +// Licensed under the MIT License. See LICENSE file in the project root for full license information. +// + +namespace MUnique.OpenMU.Tests; + +using System.Globalization; +using Microsoft.EntityFrameworkCore; +using MUnique.OpenMU.DataModel.Configuration; +using MUnique.OpenMU.Interfaces; +using MUnique.OpenMU.Persistence.EntityFramework; + +/// +/// Tests compatibility of the existing package name column with localized names. +/// +[TestFixture] +public class CashShopPackagePersistenceTests +{ + /// + /// The compiled model reads old plain names and preserves translations and source metadata on a round trip. + /// + [Test] + public void NamesUseTheExistingTextColumn() + { + var entityType = EntityDataContext.CompleteModel.GetEntityTypes().Single(type => type.ClrType.BaseType == typeof(CashShopPackage)); + var property = entityType.FindProperty(nameof(CashShopPackage.Name))!; + Assert.That(property.GetColumnType(), Is.EqualTo("text")); + var converter = property.GetTypeMapping().Converter!; + var oldName = (LocalizedString)converter.ConvertFromProvider("SD Boost Aura")!; + Assert.That(oldName.ValueInNeutralLanguage, Is.EqualTo("SD Boost Aura")); + var chinese = CultureInfo.GetCultureInfo("zh-CN"); + var name = oldName.WithTranslation(chinese, "最大SD提升光环").WithSourceKey("CashShopPackageNames/SDBoostAura").WithSourceStamp(); + var serialized = converter.ConvertToProvider(name); + Assert.That(serialized, Is.EqualTo(name.Value)); + var restored = (LocalizedString)converter.ConvertFromProvider(serialized)!; + Assert.That(restored.Value, Is.EqualTo(name.Value)); + Assert.That(restored.GetTranslation(chinese), Is.EqualTo("最大SD提升光环")); + Assert.That(restored.SourceKey, Is.EqualTo(name.SourceKey)); + } +} diff --git a/tests/MUnique.OpenMU.Web.Tests/Pages/CashShopCatalogPageTests.cs b/tests/MUnique.OpenMU.Web.Tests/Pages/CashShopCatalogPageTests.cs index 36ae8554d..812fcfd20 100644 --- a/tests/MUnique.OpenMU.Web.Tests/Pages/CashShopCatalogPageTests.cs +++ b/tests/MUnique.OpenMU.Web.Tests/Pages/CashShopCatalogPageTests.cs @@ -7,11 +7,13 @@ namespace MUnique.OpenMU.Web.Tests.Pages; using System.Globalization; using System.Threading; using Bunit; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Moq; using MUnique.OpenMU.DataModel.Configuration; using MUnique.OpenMU.DataModel.Configuration.Items; +using MUnique.OpenMU.Interfaces; using MUnique.OpenMU.Persistence; using MUnique.OpenMU.Web.AdminPanel.Pages; using MUnique.OpenMU.Web.AdminPanel.Properties; @@ -57,6 +59,8 @@ public void Setup() this._context = new BunitContext(); this._context.JSInterop.Mode = JSRuntimeMode.Loose; + this._context.Services.Configure(options => options.AddSupportedUICultures("en", "zh-CN")); + this._context.Services.AddSingleton(); this._context.Services.AddSingleton(dataSource.Object); this._context.Services.AddSingleton(Mock.Of()); this._context.Services.AddSingleton(Mock.Of()); @@ -185,6 +189,44 @@ public void CheckFindsNegativePricesAndInvalidQuantities() Assert.That(CashShopCatalogCheck.GetIssues(configuration, bundle), Is.EqualTo(new[] { Resources.CashShopIssueNegativeBundlePrice })); } + /// + /// The list and search use the UI language, and editing a translation preserves the source and neutral name. + /// + [Test] + public void LocalizedNamesAreDisplayedSearchedAndEdited() + { + var previousCulture = CultureInfo.CurrentCulture; + try + { + var chinese = CultureInfo.GetCultureInfo("zh-CN"); + CultureInfo.CurrentUICulture = chinese; + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("en"); + var package = this._gameConfiguration.CashShopConfiguration!.Packages.First(p => p.PackageSequence == 10); + package.Name = new LocalizedString("Jewel bundle").WithTranslation(chinese, "宝石礼包").WithSourceKey("Test/JewelBundle"); + package.Products.First().ItemDefinition!.Name = new LocalizedString("Jewel").WithTranslation(chinese, "宝石").WithSourceKey("Test/Jewel"); + var cut = this._context.Render(); + cut.WaitForAssertion(() => Assert.That(cut.Find("table.quickgrid").TextContent, Does.Contain("宝石礼包"))); + Assert.That(cut.Markup, Does.Not.Contain("@src=")); + cut.Find("#packageSearch").Input("宝石礼包"); + cut.WaitForAssertion(() => Assert.That(cut.Find("table.quickgrid").TextContent, Does.Not.Contain("Pet for a day"))); + cut.Find("#packageSearch").Input("Jewel bundle"); + cut.WaitForAssertion(() => Assert.That(cut.Find("table.quickgrid").TextContent, Does.Contain("宝石礼包"))); + cut.FindAll("button").First(b => b.TextContent.Contains(Resources.Edit)).Click(); + Assert.That(cut.Find("#Name").GetAttribute("value"), Is.EqualTo("Jewel bundle")); + Assert.That(cut.Find("#Name_zh-CN").GetAttribute("value"), Is.EqualTo("宝石礼包")); + Assert.That(cut.Markup, Does.Not.Contain("@src=")); + cut.Find("#Name_zh-CN").Change("自定义宝石礼包"); + cut.Find("form").Submit(); + Assert.That(package.Name.ValueInNeutralLanguage, Is.EqualTo("Jewel bundle")); + Assert.That(package.Name.GetOwnTranslation(chinese), Is.EqualTo("自定义宝石礼包")); + Assert.That(package.Name.SourceKey, Is.EqualTo("Test/JewelBundle")); + } + finally + { + CultureInfo.CurrentCulture = previousCulture; + } + } + private static CashShopPackage CreatePackage(int sequence, string name, bool isForSale, ItemDefinition? item, TimeSpan duration) { // The ids are set like the persistence context does, because the page lists the packages by them.