From 065859408f4e88ea1154b1fc76f7df5288e51b53 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 18 Feb 2022 12:31:14 -0500 Subject: Fix support for custom locale codes in asset names (#766) --- docs/release-notes.md | 1 + src/SMAPI/Framework/ContentCoordinator.cs | 33 ++++++++++++++++++++++++------- src/SMAPI/Framework/SCore.cs | 11 +++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index 5e004227..d549b99c 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ * For mod authors: * The `SDate` constructor is no longer case-sensitive for season names. * Fixed issue where suppressing `[Left|Right]Thumbstick[Down|Left]` keys would suppress the opposite direction instead. + * Fixed support for using locale codes from custom languages in asset names (e.g. `Data/Achievements.eo-EU`). * For console commands: * Fixed `player_add` with Journal Scraps and Secret Notes. diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index 49578046..61cefd12 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -14,6 +14,7 @@ using StardewModdingAPI.Metadata; using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Toolkit.Utilities; using StardewValley; +using StardewValley.GameData; using xTile; namespace StardewModdingAPI.Framework @@ -136,7 +137,7 @@ namespace StardewModdingAPI.Framework this.ContentManagers.Add(contentManagerForAssetPropagation); this.VanillaContentManager = new LocalizedContentManager(serviceProvider, rootDirectory); this.CoreAssets = new CoreAssetPropagator(this.MainContentManager, contentManagerForAssetPropagation, this.Monitor, reflection, aggressiveMemoryOptimizations); - this.LocaleCodes = new Lazy>(this.GetLocaleCodes); + this.LocaleCodes = new Lazy>(() => this.GetLocaleCodes(includeCustomLanguages: false)); } /// Get a new content manager which handles reading files from the game content folder with support for interception. @@ -196,12 +197,17 @@ namespace StardewModdingAPI.Framework return this.MainContentManager.GetLocale(LocalizedContentManager.CurrentLanguageCode); } - /// Perform any cleanup needed when the locale changes. - public void OnLocaleChanged() + /// Perform any updates needed when the game loads custom languages from Data/AdditionalLanguages. + public void OnAdditionalLanguagesInitialized() { - // rebuild locale cache (which may change due to custom mod languages) - this.LocaleCodes = new Lazy>(this.GetLocaleCodes); + // update locale cache for custom languages, and load it now (since languages added later won't work) + this.LocaleCodes = new Lazy>(() => this.GetLocaleCodes(includeCustomLanguages: true)); + _ = this.LocaleCodes.Value; + } + /// Perform any updates needed when the locale changes. + public void OnLocaleChanged() + { // reload affected content this.ContentManagerLock.InReadLock(() => { @@ -486,9 +492,22 @@ namespace StardewModdingAPI.Framework } /// Get the language enums (like ) indexed by locale code (like ja-JP). - private Dictionary GetLocaleCodes() + /// Whether to read custom languages from Data/AdditionalLanguages. + private Dictionary GetLocaleCodes(bool includeCustomLanguages) { - var map = new Dictionary(); + var map = new Dictionary(StringComparer.OrdinalIgnoreCase); + + // custom languages + if (includeCustomLanguages) + { + foreach (ModLanguage language in Game1.content.Load>("Data/AdditionalLanguages")) + { + if (!string.IsNullOrWhiteSpace(language?.LanguageCode)) + map[language.LanguageCode] = LocalizedContentManager.LanguageCode.mod; + } + } + + // vanilla languages (override custom language if they conflict) foreach (LocalizedContentManager.LanguageCode code in Enum.GetValues(typeof(LocalizedContentManager.LanguageCode))) { string locale = this.GetLocaleCode(code); diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index ef1f12fd..bfbd64ca 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -43,6 +43,7 @@ using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Toolkit.Utilities; using StardewModdingAPI.Utilities; using StardewValley; +using StardewValley.Menus; using xTile.Display; using MiniMonoModHotfix = MonoMod.Utils.MiniMonoModHotfix; using PathUtilities = StardewModdingAPI.Toolkit.Utilities.PathUtilities; @@ -121,6 +122,9 @@ namespace StardewModdingAPI.Framework /// Whether post-game-startup initialization has been performed. private bool IsInitialized; + /// Whether the game has initialized for any custom languages from Data/AdditionalLanguages. + private bool AreCustomLanguagesInitialized; + /// Whether the player just returned to the title screen. public bool JustReturnedToTitle { get; set; } @@ -986,6 +990,13 @@ namespace StardewModdingAPI.Framework // preloaded if (Context.IsSaveLoaded && Context.LoadStage != LoadStage.Loaded && Context.LoadStage != LoadStage.Ready && Game1.dayOfMonth != 0) this.OnLoadStageChanged(LoadStage.Loaded); + + // additional languages initialized + if (!this.AreCustomLanguagesInitialized && TitleMenu.ticksUntilLanguageLoad < 0) + { + this.AreCustomLanguagesInitialized = true; + this.ContentCore.OnAdditionalLanguagesInitialized(); + } } /********* -- cgit