diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentCoordinator.cs | 7 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentManagers/BaseContentManager.cs | 3 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentManagers/GameContentManager.cs | 23 | ||||
-rw-r--r-- | src/SMAPI/Framework/ContentManagers/IContentManager.cs | 3 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 6 | ||||
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 8 |
7 files changed, 43 insertions, 8 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 6aa3c024..84738ff7 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ These changes have not been released yet. * Fixed Save Backup not pruning old backups if they're uncompressed. * Fixed issues when a farmhand reconnects before the game notices they're disconnected. * Fixed 'received message' logs shown in non-developer mode. + * Fixed some assets not updated when you switch language to English. * For modders: * Added support for content pack translations. 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); } + /// <summary>Perform any cleanup needed when the locale changes.</summary> + public void OnLocaleChanged() + { + foreach (IContentManager contentManager in this.ContentManagers) + contentManager.OnLocaleChanged(); + } + /// <summary>Get whether this asset is mapped to a mod folder.</summary> /// <param name="key">The asset key.</param> 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 } } + /// <summary>Perform any cleanup needed when the locale changes.</summary> + public virtual void OnLocaleChanged() { } + /// <summary>Normalise path separators in a file path. For asset keys, see <see cref="AssertAndNormaliseAssetName"/> instead.</summary> /// <param name="path">The file path to normalise.</param> [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; } + /// <summary>Perform any cleanup needed when the locale changes.</summary> + public override void OnLocaleChanged() + { + base.OnLocaleChanged(); + + // find assets for which a translatable version was loaded + HashSet<string> removeAssetNames = new HashSet<string>(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); + } + /// <summary>Create a new content manager for temporary use.</summary> 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 /// <param name="asset">The asset to clone.</param> T CloneIfPossible<T>(T asset); + /// <summary>Perform any cleanup needed when the locale changes.</summary> + void OnLocaleChanged(); + /// <summary>Normalise path separators in a file path. For asset keys, see <see cref="AssertAndNormaliseAssetName"/> instead.</summary> /// <param name="path">The file path to normalise.</param> [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 /// <summary>Handle the game changing locale.</summary> 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 /// <summary>Whether the game is creating the save file and SMAPI has already raised <see cref="IGameLoopEvents.SaveCreating"/>.</summary> private bool IsBetweenCreateEvents; - /// <summary>A callback to invoke after the content language changes.</summary> - private readonly Action OnLocaleChanged; - /// <summary>A callback to invoke the first time *any* game content manager loads an asset.</summary> private readonly Action OnLoadingFirstAsset; @@ -137,10 +134,9 @@ namespace StardewModdingAPI.Framework /// <param name="jsonHelper">Encapsulates SMAPI's JSON file parsing.</param> /// <param name="modRegistry">Tracks the installed mods.</param> /// <param name="deprecationManager">Manages deprecation warnings.</param> - /// <param name="onLocaleChanged">A callback to invoke after the content language changes.</param> /// <param name="onGameInitialised">A callback to invoke after the game finishes initialising.</param> /// <param name="onGameExiting">A callback to invoke when the game exits.</param> - 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(); } |