From f83b4a9138fd34f0fb9d466fae5a27481f77cb2a Mon Sep 17 00:00:00 2001 From: CWX Date: Thu, 17 Apr 2025 13:19:55 +0100 Subject: [PATCH] implemented ability to add custom locales change was relatively small so added it directly to localService anything dealing with locales should use this service and not directly with DatabaseService.GetTables().Locales.Global as injected locales will be lost due to lazyloading --- .../Services/CustomLocaleService.cs | 75 --------------- .../Services/LocaleService.cs | 94 +++++++++++++++++-- 2 files changed, 85 insertions(+), 84 deletions(-) delete mode 100644 Libraries/SPTarkov.Server.Core/Services/CustomLocaleService.cs diff --git a/Libraries/SPTarkov.Server.Core/Services/CustomLocaleService.cs b/Libraries/SPTarkov.Server.Core/Services/CustomLocaleService.cs deleted file mode 100644 index e6142c7f..00000000 --- a/Libraries/SPTarkov.Server.Core/Services/CustomLocaleService.cs +++ /dev/null @@ -1,75 +0,0 @@ -using SPTarkov.Server.Core.Models.Utils; -using SPTarkov.Common.Annotations; - -namespace SPTarkov.Server.Core.Services; - -[Injectable(InjectionType.Singleton)] -public class CustomLocaleService( - ISptLogger logger -) -{ - protected Dictionary> customServerLocales = new(); - protected Dictionary> customClientLocales = new(); - - - /// - /// Path should link to a folder containing every locale that should be added to the server locales - /// e.g. en.json for english, fr.json for french.
- /// Inside each JSON should be a Dictionary of the locale key and localised text - ///
- /// en/fr/de - /// locale key to store values against - /// Localised string to store - public void AddServerLocales(string locale, string localeKey, string localeValue) - { - AddToDictionary(locale, localeKey, localeValue, customServerLocales); - } - - /// - /// Path should link to a folder containing every locale that should be added to the game locales - /// e.g. en.json for english, fr.json for french.
- /// Inside each JSON should be a Dictionary of the locale key and localised text - ///
- /// en/fr/de - /// locale key to store values against - /// Localised string to store - public void AddGameLocales(string locale, string localeKey, string localeValue) - { - AddToDictionary(locale, localeKey, localeValue, customClientLocales); - } - - protected void AddToDictionary(string locale, string localeKey, string localeValue, - Dictionary> dictionaryToAddTo) - { - dictionaryToAddTo.TryAdd(locale, new Dictionary()); - if (!dictionaryToAddTo.TryGetValue(locale, out var localeDictToAddTo)) - { - logger.Error($"Unable to get custom locale dictionary keyed by: {locale}"); - - return; - } - - if (!localeDictToAddTo.TryAdd(localeKey, localeValue)) - { - logger.Error($"Unable to add: {localeKey} {localeValue} to custom locale dictionary: {locale}"); - } - } - - public string? GetServerValue(string locale, string localeKey) - { - return GetValueFromDictionary(locale, localeKey, customServerLocales); - } - - public string? GetClientValue(string locale, string localeKey) - { - return GetValueFromDictionary(locale, localeKey, customClientLocales); - } - - protected string? GetValueFromDictionary(string locale, string localeKey, - Dictionary> dictionaryToGetFrom) - { - return dictionaryToGetFrom.TryGetValue(locale, out var localeDictToGetFrom) - ? localeDictToGetFrom.GetValueOrDefault(localeKey) // Locale exists, look up value or return null - : null; // No locale (e.g. en/fr/de) at all - } -} diff --git a/Libraries/SPTarkov.Server.Core/Services/LocaleService.cs b/Libraries/SPTarkov.Server.Core/Services/LocaleService.cs index 7fbdb73d..878b64d4 100644 --- a/Libraries/SPTarkov.Server.Core/Services/LocaleService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/LocaleService.cs @@ -3,6 +3,7 @@ using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; using SPTarkov.Common.Annotations; +using SPTarkov.Server.Core.Utils.Json; namespace SPTarkov.Server.Core.Services; @@ -13,24 +14,68 @@ public class LocaleService( ConfigServer _configServer ) { + // we have to LazyLoad the data from the database and then combine it with the custom data before returning it protected LocaleConfig _localeConfig = _configServer.GetConfig(); + protected Dictionary> customClientLocales = new Dictionary>(); /// - /// Get the eft globals db file based on the configured locale in config/locale.json, if not found, fall back to 'en' + /// Get the eft globals db file based on the configured locale in config/locale.json, if not found, fall back to 'en' + /// This will contain Custom locales added by mods /// - /// Dictionary - public Dictionary GetLocaleDb() + /// Dictionary of locales for desired language - en/fr/cn + public Dictionary GetLocaleDb(string? language = null) { - if (_databaseServer.GetTables().Locales.Global.TryGetValue(GetDesiredGameLocale(), out var desiredLocale)) + var languageToUse = string.IsNullOrEmpty(language) ? GetDesiredGameLocale() : language; + Dictionary? localeToReturn; + + // if it can't get locales for language provided, default to en + if (TryGetLocaleDbWithCustomLocales(languageToUse, out localeToReturn) || + TryGetLocaleDbWithCustomLocales("en", out localeToReturn)) { - return desiredLocale.Value; + // TODO: need to see if this needs to be cloned + return RemovePraporTestMessage(localeToReturn); } - _logger.Warning( - $"Unable to find desired locale file using locale: {GetDesiredGameLocale()} from config/locale.json, falling back to 'en'" - ); + throw new Exception($"unable to get locales from either {languageToUse} or en"); + } - return _databaseServer.GetTables().Locales.Global["en"].Value; + /// + /// Attempts to retrieve the locale database for the specified language key, including custom locales if available. + /// + /// The language key for which the locale database should be retrieved. + /// The resulting locale database as a dictionary, or null if the operation fails. + /// True if the locale database was successfully retrieved, otherwise false. + private bool TryGetLocaleDbWithCustomLocales(string languageKey, out Dictionary? localeToReturn) + { + localeToReturn = null; + if (!_databaseServer.GetTables().Locales.Global.TryGetValue(languageKey, out var keyedLocales)) + { + return false; + } + + localeToReturn = keyedLocales.Value; + + if (customClientLocales.TryGetValue(languageKey, out var customClientLocale)) + { + // there were custom locales for this language + localeToReturn = CombineDbWithCustomLocales(localeToReturn, customClientLocale); + } + + return true; + } + + + /// + /// Combines the provided database locales with custom locales, ensuring that all entries are merged into a single dictionary. + /// Custom locale entries will overwrite existing keys from the database locales if conflicts occur. + /// + /// + /// The dictionary containing locale entries from the database. + /// The dictionary containing custom locale entries to be merged. + /// A dictionary representing the merged result of database and custom locales. + private Dictionary CombineDbWithCustomLocales(Dictionary dbLocales, Dictionary customLocales) + { + return dbLocales.Union(customLocales).ToDictionary(x => x.Key, x => x.Value); } /// @@ -179,4 +224,35 @@ public class LocaleService( { return GetLocaleDb().Keys.Where(x => x.StartsWith(partialKey)).ToList(); } + + public void AddCustomClientLocale(string locale, string localeKey, string localeValue) + { + AddToDictionary(locale, localeKey, localeValue, customClientLocales); + } + + private void AddToDictionary(string locale, string localeKey, string localeValue, + Dictionary> dictionaryToAddTo) + { + dictionaryToAddTo.TryAdd(locale, new Dictionary()); + if (!dictionaryToAddTo.TryGetValue(locale, out var localeDictToAddTo)) + { + _logger.Error($"Unable to get custom locale dictionary keyed by: {locale}"); + + return; + } + + if (!localeDictToAddTo.TryAdd(localeKey, localeValue)) + { + _logger.Error($"Unable to add: {localeKey} {localeValue} to custom locale dictionary: {locale}"); + } + } + + /// + /// Blank out the "test" mail message from prapor + /// + protected Dictionary RemovePraporTestMessage(Dictionary dbLocales) + { + dbLocales["61687e2c3e526901fa76baf9"] = ""; + return dbLocales; + } }