diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentCoordinator.cs | 33 | ||||
-rw-r--r-- | 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<Dictionary<string, LocalizedContentManager.LanguageCode>>(this.GetLocaleCodes); + this.LocaleCodes = new Lazy<Dictionary<string, LocalizedContentManager.LanguageCode>>(() => this.GetLocaleCodes(includeCustomLanguages: false)); } /// <summary>Get a new content manager which handles reading files from the game content folder with support for interception.</summary> @@ -196,12 +197,17 @@ namespace StardewModdingAPI.Framework return this.MainContentManager.GetLocale(LocalizedContentManager.CurrentLanguageCode); } - /// <summary>Perform any cleanup needed when the locale changes.</summary> - public void OnLocaleChanged() + /// <summary>Perform any updates needed when the game loads custom languages from <c>Data/AdditionalLanguages</c>.</summary> + public void OnAdditionalLanguagesInitialized() { - // rebuild locale cache (which may change due to custom mod languages) - this.LocaleCodes = new Lazy<Dictionary<string, LocalizedContentManager.LanguageCode>>(this.GetLocaleCodes); + // update locale cache for custom languages, and load it now (since languages added later won't work) + this.LocaleCodes = new Lazy<Dictionary<string, LocalizedContentManager.LanguageCode>>(() => this.GetLocaleCodes(includeCustomLanguages: true)); + _ = this.LocaleCodes.Value; + } + /// <summary>Perform any updates needed when the locale changes.</summary> + public void OnLocaleChanged() + { // reload affected content this.ContentManagerLock.InReadLock(() => { @@ -486,9 +492,22 @@ namespace StardewModdingAPI.Framework } /// <summary>Get the language enums (like <see cref="LocalizedContentManager.LanguageCode.ja"/>) indexed by locale code (like <c>ja-JP</c>).</summary> - private Dictionary<string, LocalizedContentManager.LanguageCode> GetLocaleCodes() + /// <param name="includeCustomLanguages">Whether to read custom languages from <c>Data/AdditionalLanguages</c>.</param> + private Dictionary<string, LocalizedContentManager.LanguageCode> GetLocaleCodes(bool includeCustomLanguages) { - var map = new Dictionary<string, LocalizedContentManager.LanguageCode>(); + var map = new Dictionary<string, LocalizedContentManager.LanguageCode>(StringComparer.OrdinalIgnoreCase); + + // custom languages + if (includeCustomLanguages) + { + foreach (ModLanguage language in Game1.content.Load<List<ModLanguage>>("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 /// <summary>Whether post-game-startup initialization has been performed.</summary> private bool IsInitialized; + /// <summary>Whether the game has initialized for any custom languages from <c>Data/AdditionalLanguages</c>.</summary> + private bool AreCustomLanguagesInitialized; + /// <summary>Whether the player just returned to the title screen.</summary> 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(); + } } /********* |