update for custom languages

This commit is contained in:
Jesse Plamondon-Willard 2021-09-15 00:27:17 -04:00
parent 1ab0420b6d
commit 25384ce6bc
No known key found for this signature in database
GPG Key ID: CF8B1456B3E29F49
4 changed files with 45 additions and 19 deletions

View File

@ -64,6 +64,9 @@ namespace StardewModdingAPI.Framework
/// <summary>An unmodified content manager which doesn't intercept assets, used to compare asset data.</summary>
private readonly LocalizedContentManager VanillaContentManager;
/// <summary>The language enum values indexed by locale code.</summary>
private Lazy<IDictionary<string, LocalizedContentManager.LanguageCode>> LocaleCodes;
/*********
** Accessors
@ -133,6 +136,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<IDictionary<string, LocalizedContentManager.LanguageCode>>(this.GetLocaleCodes);
}
/// <summary>Get a new content manager which handles reading files from the game content folder with support for interception.</summary>
@ -195,6 +199,10 @@ namespace StardewModdingAPI.Framework
/// <summary>Perform any cleanup needed when the locale changes.</summary>
public void OnLocaleChanged()
{
// rebuild locale cache (which may change due to custom mod languages)
this.LocaleCodes = new Lazy<IDictionary<string, LocalizedContentManager.LanguageCode>>(this.GetLocaleCodes);
// reload affected content
this.ContentManagerLock.InReadLock(() =>
{
foreach (IContentManager contentManager in this.ContentManagers)
@ -408,6 +416,25 @@ namespace StardewModdingAPI.Framework
return tilesheets ?? new TilesheetReference[0];
}
/// <summary>Get the language enum which corresponds to a locale code (e.g. <see cref="LocalizedContentManager.LanguageCode.fr"/> given <c>fr-FR</c>).</summary>
/// <param name="locale">The locale code to search. This must exactly match the language; no fallback is performed.</param>
/// <param name="language">The matched language enum, if any.</param>
/// <returns>Returns whether a valid language was found.</returns>
public bool TryGetLanguageEnum(string locale, out LocalizedContentManager.LanguageCode language)
{
return this.LocaleCodes.Value.TryGetValue(locale, out language);
}
/// <summary>Get the locale code which corresponds to a language enum (e.g. <c>fr-FR</c> given <see cref="LocalizedContentManager.LanguageCode.fr"/>).</summary>
/// <param name="language">The language enum to search.</param>
public string GetLocaleCode(LocalizedContentManager.LanguageCode language)
{
if (language == LocalizedContentManager.LanguageCode.mod && LocalizedContentManager.CurrentModLanguage == null)
return null;
return Game1.content.LanguageCodeString(language);
}
/// <summary>Dispose held resources.</summary>
public void Dispose()
{
@ -457,5 +484,19 @@ namespace StardewModdingAPI.Framework
return false;
}
}
/// <summary>Get the language enums (like <see cref="LocalizedContentManager.LanguageCode.ja"/>) indexed by locale code (like <c>ja-JP</c>).</summary>
private IDictionary<string, LocalizedContentManager.LanguageCode> GetLocaleCodes()
{
IDictionary<string, LocalizedContentManager.LanguageCode> map = new Dictionary<string, LocalizedContentManager.LanguageCode>();
foreach (LocalizedContentManager.LanguageCode code in Enum.GetValues(typeof(LocalizedContentManager.LanguageCode)))
{
string locale = this.GetLocaleCode(code);
if (locale != null)
map[locale] = code;
}
return map;
}
}
}

View File

@ -38,9 +38,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <summary>A callback to invoke when the content manager is being disposed.</summary>
private readonly Action<BaseContentManager> OnDisposing;
/// <summary>The language enum values indexed by locale code.</summary>
protected IDictionary<string, LanguageCode> LanguageCodes { get; }
/// <summary>A list of disposable assets.</summary>
private readonly List<WeakReference<IDisposable>> Disposables = new List<WeakReference<IDisposable>>();
@ -92,7 +89,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
this.AggressiveMemoryOptimizations = aggressiveMemoryOptimizations;
// get asset data
this.LanguageCodes = this.GetKeyLocales().ToDictionary(p => p.Value, p => p.Key, StringComparer.OrdinalIgnoreCase);
this.BaseDisposableReferences = reflection.GetField<List<IDisposable>>(this, "disposableAssets").GetValue();
}
@ -292,7 +288,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
if (lastSepIndex >= 0)
{
string suffix = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1);
if (this.LanguageCodes.ContainsKey(suffix))
if (this.Coordinator.TryGetLanguageEnum(suffix, out _))
{
assetName = cacheKey.Substring(0, lastSepIndex);
localeCode = cacheKey.Substring(lastSepIndex + 1, cacheKey.Length - lastSepIndex - 1);
@ -311,17 +307,6 @@ namespace StardewModdingAPI.Framework.ContentManagers
/// <param name="language">The language to check.</param>
protected abstract bool IsNormalizedKeyLoaded(string normalizedAssetName, LanguageCode language);
/// <summary>Get the locale codes (like <c>ja-JP</c>) used in asset keys.</summary>
private IDictionary<LanguageCode, string> GetKeyLocales()
{
// create locale => code map
IDictionary<LanguageCode, string> map = new Dictionary<LanguageCode, string>();
foreach (LanguageCode code in Enum.GetValues(typeof(LanguageCode)))
map[code] = this.GetLocale(code);
return map;
}
/// <summary>Get the asset name from a cache key.</summary>
/// <param name="cacheKey">The input cache key.</param>
private string GetAssetName(string cacheKey)

View File

@ -249,7 +249,7 @@ namespace StardewModdingAPI.Framework.ContentManagers
// extract language code
int splitIndex = rawAsset.LastIndexOf('.');
if (splitIndex != -1 && this.LanguageCodes.TryGetValue(rawAsset.Substring(splitIndex + 1), out language))
if (splitIndex != -1 && this.Coordinator.TryGetLanguageEnum(rawAsset.Substring(splitIndex + 1), out language))
{
assetName = rawAsset.Substring(0, splitIndex);
return true;

View File

@ -751,7 +751,7 @@ namespace StardewModdingAPI.Framework
** Locale changed events
*********/
if (state.Locale.IsChanged)
this.Monitor.Log($"Context: locale set to {state.Locale.New}.");
this.Monitor.Log($"Context: locale set to {state.Locale.New} ({this.ContentCore.GetLocaleCode(state.Locale.New)}).");
/*********
** Load / return-to-title events
@ -761,7 +761,7 @@ namespace StardewModdingAPI.Framework
else if (Context.IsWorldReady && Context.LoadStage != LoadStage.Ready)
{
// print context
string context = $"Context: loaded save '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}, locale set to {this.ContentCore.Language}.";
string context = $"Context: loaded save '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}, locale set to {this.ContentCore.GetLocale()}.";
if (Context.IsMultiplayer)
{
int onlineCount = Game1.getOnlineFarmers().Count();