diff --git a/Robust.Shared/Localization/LocalizationManager.cs b/Robust.Shared/Localization/LocalizationManager.cs index cc719c6202e..a169d2dd384 100644 --- a/Robust.Shared/Localization/LocalizationManager.cs +++ b/Robust.Shared/Localization/LocalizationManager.cs @@ -27,6 +27,7 @@ namespace Robust.Shared.Localization internal abstract partial class LocalizationManager : ILocalizationManagerInternal { protected static readonly ResPath LocaleDirPath = new("/Locale"); + protected static readonly ResPath UploadedDirPath = new("/Uploaded"); [Dependency] private readonly IConfigurationManager _configuration = default!; [Dependency] private readonly IResourceManager _res = default!; @@ -403,6 +404,20 @@ public List GetFoundCultures() result.Add(CultureInfo.GetCultureInfo(cultureName, predefinedOnly: false)); } + var uploadedFiles = _res.ContentFindFiles(UploadedDirPath) + .Where(c => c.Filename.EndsWith(".ftl", StringComparison.InvariantCultureIgnoreCase)); + + foreach (var file in uploadedFiles) + { + var cultureName = Path.GetFileNameWithoutExtension(file.Filename); + if (CultureInfo.GetCultures(CultureTypes.AllCultures).Any(c => c.Name.Equals(cultureName, StringComparison.InvariantCultureIgnoreCase))) + { + var culture = CultureInfo.GetCultureInfo(cultureName, predefinedOnly: false); + if (!result.Contains(culture)) + result.Add(culture); + } + } + return result; } @@ -485,10 +500,13 @@ private void _initData(IResourceManager resourceManager, CultureInfo culture, Fl { // Load data from .ftl files. // Data is loaded from /Locale//* + // and from /Uploaded/**/Locale//* var root = LocaleDirPath / culture.Name; var files = resourceManager.ContentFindFiles(root) + .Concat(resourceManager.ContentFindFiles(UploadedDirPath) + .Where(c => c.CanonPath.Contains($"/Locale/{culture.Name}/", StringComparison.InvariantCultureIgnoreCase))) .Where(c => c.Filename.EndsWith(".ftl", StringComparison.InvariantCultureIgnoreCase)) .ToArray(); diff --git a/Robust.Shared/Upload/SharedNetworkResourceManager.cs b/Robust.Shared/Upload/SharedNetworkResourceManager.cs index 84fac8f166d..0749c3dd814 100644 --- a/Robust.Shared/Upload/SharedNetworkResourceManager.cs +++ b/Robust.Shared/Upload/SharedNetworkResourceManager.cs @@ -7,6 +7,7 @@ using Robust.Shared.Asynchronous; using Robust.Shared.ContentPack; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Network; using Robust.Shared.Network.Transfer; @@ -38,6 +39,7 @@ public abstract class SharedNetworkResourceManager : IDisposable, IPostInjectIni [Dependency] protected readonly IResourceManager ResourceManager = default!; [Dependency] protected readonly ITransferManager TransferManager = default!; [Dependency] protected readonly ILogManager LogManager = default!; + [Dependency] protected readonly ILocalizationManager LocalizationManager = default!; [Dependency] private readonly ITaskManager _taskManager = default!; protected ISawmill Sawmill = default!; @@ -112,9 +114,13 @@ protected virtual void ValidateUpload(uint size) protected async Task> IngestFileStream(Stream stream) { var list = new List<(ResPath Relative, byte[] Data)>(); + var anyLoc = false; await foreach (var (relative, data) in ReadTransferStream(stream).ConfigureAwait(false)) { + if (relative.Extension == "ftl") + anyLoc = true; + Sawmill.Verbose($"Storing uploaded file: {relative} ({ByteHelpers.FormatBytes(data.Length)})"); _taskManager.RunOnMainThread(() => { @@ -123,6 +129,14 @@ protected virtual void ValidateUpload(uint size) list.Add((relative, data)); } + if (anyLoc) + { + _taskManager.RunOnMainThread(() => + { + LocalizationManager.ReloadLocalizations(); + }); + } + return list; }