From 6c220453e16c6cb5ad150b61cf02685a97557b3c Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 15 Apr 2019 00:40:45 -0400 Subject: fix translatable assets not updated when switching language (#586) --- src/SMAPI/Framework/ContentCoordinator.cs | 7 +++++++ .../ContentManagers/BaseContentManager.cs | 3 +++ .../ContentManagers/GameContentManager.cs | 23 ++++++++++++++++++++++ .../Framework/ContentManagers/IContentManager.cs | 3 +++ src/SMAPI/Framework/SCore.cs | 6 +++++- src/SMAPI/Framework/SGame.cs | 8 +------- 6 files changed, 42 insertions(+), 8 deletions(-) (limited to 'src/SMAPI/Framework') diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs index caeb7ee9..25eeb2ef 100644 --- a/src/SMAPI/Framework/ContentCoordinator.cs +++ b/src/SMAPI/Framework/ContentCoordinator.cs @@ -114,6 +114,13 @@ namespace StardewModdingAPI.Framework return this.MainContentManager.GetLocale(LocalizedContentManager.CurrentLanguageCode); } + /// Perform any cleanup needed when the locale changes. + public void OnLocaleChanged() + { + foreach (IContentManager contentManager in this.ContentManagers) + contentManager.OnLocaleChanged(); + } + /// Get whether this asset is mapped to a mod folder. /// The asset key. public bool IsManagedAssetKey(string key) diff --git a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs index 7821e454..b2b3769b 100644 --- a/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/BaseContentManager.cs @@ -138,6 +138,9 @@ namespace StardewModdingAPI.Framework.ContentManagers } } + /// Perform any cleanup needed when the locale changes. + public virtual void OnLocaleChanged() { } + /// Normalise path separators in a file path. For asset keys, see instead. /// The file path to normalise. [Pure] diff --git a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs index f159f035..55cf15ec 100644 --- a/src/SMAPI/Framework/ContentManagers/GameContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/GameContentManager.cs @@ -112,6 +112,29 @@ namespace StardewModdingAPI.Framework.ContentManagers return data; } + /// Perform any cleanup needed when the locale changes. + public override void OnLocaleChanged() + { + base.OnLocaleChanged(); + + // find assets for which a translatable version was loaded + HashSet removeAssetNames = new HashSet(StringComparer.InvariantCultureIgnoreCase); + foreach (string key in this.IsLocalisableLookup.Where(p => p.Value).Select(p => p.Key)) + removeAssetNames.Add(this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) ? assetName : key); + + // invalidate translatable assets + string[] invalidated = this + .InvalidateCache((key, type) => + removeAssetNames.Contains(key) + || (this.TryParseExplicitLanguageAssetKey(key, out string assetName, out _) && removeAssetNames.Contains(assetName)) + ) + .Select(p => p.Item1) + .OrderBy(p => p, StringComparer.InvariantCultureIgnoreCase) + .ToArray(); + if (invalidated.Any()) + this.Monitor.Log($"Invalidated {invalidated.Length} asset names: {string.Join(", ", invalidated)} for locale change.", LogLevel.Trace); + } + /// Create a new content manager for temporary use. public override LocalizedContentManager CreateTemporary() { diff --git a/src/SMAPI/Framework/ContentManagers/IContentManager.cs b/src/SMAPI/Framework/ContentManagers/IContentManager.cs index 17618edd..66ef9181 100644 --- a/src/SMAPI/Framework/ContentManagers/IContentManager.cs +++ b/src/SMAPI/Framework/ContentManagers/IContentManager.cs @@ -52,6 +52,9 @@ namespace StardewModdingAPI.Framework.ContentManagers /// The asset to clone. T CloneIfPossible(T asset); + /// Perform any cleanup needed when the locale changes. + void OnLocaleChanged(); + /// Normalise path separators in a file path. For asset keys, see instead. /// The file path to normalise. [Pure] diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index f64af82b..e8d5b672 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -208,6 +208,9 @@ namespace StardewModdingAPI.Framework // add more leniant assembly resolvers AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => AssemblyLoader.ResolveAssembly(e.Name); + // hook locale event + LocalizedContentManager.OnLanguageChange += locale => this.OnLocaleChanged(); + // override game SGame.ConstructorHack = new SGameConstructorHack(this.Monitor, this.Reflection, this.Toolkit.JsonHelper, this.InitialiseBeforeFirstAssetLoaded); this.GameInstance = new SGame( @@ -218,7 +221,6 @@ namespace StardewModdingAPI.Framework jsonHelper: this.Toolkit.JsonHelper, modRegistry: this.ModRegistry, deprecationManager: SCore.DeprecationManager, - onLocaleChanged: this.OnLocaleChanged, onGameInitialised: this.InitialiseAfterGameStart, onGameExiting: this.Dispose ); @@ -442,6 +444,8 @@ namespace StardewModdingAPI.Framework /// Handle the game changing locale. private void OnLocaleChanged() { + this.ContentCore.OnLocaleChanged(); + // get locale string locale = this.ContentCore.GetLocale(); LocalizedContentManager.LanguageCode languageCode = this.ContentCore.Language; diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index 002a5d1b..684ff3ba 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -72,9 +72,6 @@ namespace StardewModdingAPI.Framework /// Whether the game is creating the save file and SMAPI has already raised . private bool IsBetweenCreateEvents; - /// A callback to invoke after the content language changes. - private readonly Action OnLocaleChanged; - /// A callback to invoke the first time *any* game content manager loads an asset. private readonly Action OnLoadingFirstAsset; @@ -137,10 +134,9 @@ namespace StardewModdingAPI.Framework /// Encapsulates SMAPI's JSON file parsing. /// Tracks the installed mods. /// Manages deprecation warnings. - /// A callback to invoke after the content language changes. /// A callback to invoke after the game finishes initialising. /// A callback to invoke when the game exits. - internal SGame(IMonitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onLocaleChanged, Action onGameInitialised, Action onGameExiting) + internal SGame(IMonitor monitor, IMonitor monitorForGame, Reflector reflection, EventManager eventManager, JsonHelper jsonHelper, ModRegistry modRegistry, DeprecationManager deprecationManager, Action onGameInitialised, Action onGameExiting) { this.OnLoadingFirstAsset = SGame.ConstructorHack.OnLoadingFirstAsset; SGame.ConstructorHack = null; @@ -159,7 +155,6 @@ namespace StardewModdingAPI.Framework this.ModRegistry = modRegistry; this.Reflection = reflection; this.DeprecationManager = deprecationManager; - this.OnLocaleChanged = onLocaleChanged; this.OnGameInitialised = onGameInitialised; this.OnGameExiting = onGameExiting; Game1.input = new SInputState(); @@ -467,7 +462,6 @@ namespace StardewModdingAPI.Framework if (this.Watchers.LocaleWatcher.IsChanged) { this.Monitor.Log($"Context: locale set to {this.Watchers.LocaleWatcher.CurrentValue}.", LogLevel.Trace); - this.OnLocaleChanged(); this.Watchers.LocaleWatcher.Reset(); } -- cgit