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; + } }