diff --git a/OpenRA.Game/FluentBundle.cs b/OpenRA.Game/FluentBundle.cs index ab722efd2e..704068330a 100644 --- a/OpenRA.Game/FluentBundle.cs +++ b/OpenRA.Game/FluentBundle.cs @@ -56,28 +56,17 @@ namespace OpenRA public FluentBundle(string language, string[] paths, IReadOnlyFileSystem fileSystem) : this(language, paths, fileSystem, error => Log.Write("debug", error.Message)) { } + public FluentBundle(string language, string[] paths, IReadOnlyFileSystem fileSystem, string text) + : this(language, paths, fileSystem, text, error => Log.Write("debug", error.Message)) { } + public FluentBundle(string language, string[] paths, IReadOnlyFileSystem fileSystem, Action onError) - { - if (paths == null || paths.Length == 0) - return; - - bundle = LinguiniBuilder.Builder() - .CultureInfo(new CultureInfo(language)) - .SkipResources() - .SetUseIsolating(false) - .UseConcurrent() - .UncheckedBuild(); - - Load(language, paths, fileSystem, onError); - } + : this(language, paths, fileSystem, null, onError) { } public FluentBundle(string language, string text, Action onError) - { - var parser = new LinguiniParser(text); - var resource = parser.Parse(); - foreach (var error in resource.Errors) - onError(error); + : this(language, null, null, text, onError) { } + public FluentBundle(string language, string[] paths, IReadOnlyFileSystem fileSystem, string text, Action onError) + { bundle = LinguiniBuilder.Builder() .CultureInfo(new CultureInfo(language)) .SkipResources() @@ -85,31 +74,39 @@ namespace OpenRA .UseConcurrent() .UncheckedBuild(); - bundle.AddResourceOverriding(resource); - } - - void Load(string language, string[] paths, IReadOnlyFileSystem fileSystem, Action onError) - { - // Always load english strings to provide a fallback for missing translations. - // It is important to load the english files first so the chosen language's files can override them. - var resolvedPaths = paths.Where(t => t.EndsWith("en.ftl", StringComparison.Ordinal)).ToList(); - foreach (var t in paths) - if (t.EndsWith($"{language}.ftl", StringComparison.Ordinal)) - resolvedPaths.Add(t); - - foreach (var path in resolvedPaths.Distinct()) + if (paths != null && paths.Length > 0) { - var stream = fileSystem.Open(path); - using (var reader = new StreamReader(stream)) - { - var parser = new LinguiniParser(reader); - var resource = parser.Parse(); - foreach (var error in resource.Errors) - onError(error); + // Always load english strings to provide a fallback for missing translations. + // It is important to load the english files first so the chosen language's files can override them. + var resolvedPaths = paths.Where(t => t.EndsWith("en.ftl", StringComparison.Ordinal)).ToList(); + foreach (var t in paths) + if (t.EndsWith($"{language}.ftl", StringComparison.Ordinal)) + resolvedPaths.Add(t); - bundle.AddResourceOverriding(resource); + foreach (var path in resolvedPaths.Distinct()) + { + var stream = fileSystem.Open(path); + using (var reader = new StreamReader(stream)) + { + var parser = new LinguiniParser(reader); + var resource = parser.Parse(); + foreach (var error in resource.Errors) + onError(error); + + bundle.AddResourceOverriding(resource); + } } } + + if (!string.IsNullOrEmpty(text)) + { + var parser = new LinguiniParser(text); + var resource = parser.Parse(); + foreach (var error in resource.Errors) + onError(error); + + bundle.AddResourceOverriding(resource); + } } public string GetMessage(string key, object[] args = null) diff --git a/OpenRA.Game/FluentProvider.cs b/OpenRA.Game/FluentProvider.cs index 703ef61835..25f1b7c8fd 100644 --- a/OpenRA.Game/FluentProvider.cs +++ b/OpenRA.Game/FluentProvider.cs @@ -25,8 +25,8 @@ namespace OpenRA lock (SyncObject) { modFluentBundle = new FluentBundle(Game.Settings.Player.Language, modData.Manifest.Translations, fileSystem); - mapFluentBundle = fileSystem is Map map && map.TranslationDefinitions != null - ? new FluentBundle(Game.Settings.Player.Language, FieldLoader.GetValue("value", map.TranslationDefinitions.Value), fileSystem) + mapFluentBundle = fileSystem is Map map && map.FluentMessageDefinitions != null + ? new FluentBundle(Game.Settings.Player.Language, FieldLoader.GetValue("value", map.FluentMessageDefinitions.Value), fileSystem) : null; } } diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 7639ed3b5e..5385a698fd 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -172,7 +172,7 @@ namespace OpenRA new("Players", nameof(PlayerDefinitions)), new("Actors", nameof(ActorDefinitions)), new("Rules", nameof(RuleDefinitions), required: false), - new("Translations", nameof(TranslationDefinitions), required: false), + new("Translations", nameof(FluentMessageDefinitions), required: false), new("Sequences", nameof(SequenceDefinitions), required: false), new("ModelSequences", nameof(ModelSequenceDefinitions), required: false), new("Weapons", nameof(WeaponDefinitions), required: false), @@ -203,7 +203,7 @@ namespace OpenRA // Custom map yaml. Public for access by the map importers and lint checks public MiniYaml RuleDefinitions; - public MiniYaml TranslationDefinitions; + public MiniYaml FluentMessageDefinitions; public MiniYaml SequenceDefinitions; public MiniYaml ModelSequenceDefinitions; public MiniYaml WeaponDefinitions; diff --git a/OpenRA.Game/Map/MapPreview.cs b/OpenRA.Game/Map/MapPreview.cs index 143656c0d7..1e5d4118eb 100644 --- a/OpenRA.Game/Map/MapPreview.cs +++ b/OpenRA.Game/Map/MapPreview.cs @@ -90,6 +90,7 @@ namespace OpenRA public MiniYaml NotificationDefinitions; public MiniYaml SequenceDefinitions; public MiniYaml ModelSequenceDefinitions; + public MiniYaml FluentMessageDefinitions; public FluentBundle FluentBundle { get; private set; } public ActorInfo WorldActorInfo { get; private set; } @@ -335,7 +336,7 @@ namespace OpenRA innerData.SetCustomRules(modData, this, new Dictionary() { { "Rules", map.RuleDefinitions }, - { "Translations", map.TranslationDefinitions }, + { "Translations", map.FluentMessageDefinitions }, { "Weapons", map.WeaponDefinitions }, { "Voices", map.VoiceDefinitions }, { "Music", map.MusicDefinitions }, diff --git a/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs b/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs index cfa729392a..1abf1cb384 100644 --- a/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs +++ b/OpenRA.Mods.Common/Lint/CheckFluentReferences.cs @@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Lint void ILintMapPass.Run(Action emitError, Action emitWarning, ModData modData, Map map) { - if (map.TranslationDefinitions == null) + if (map.FluentMessageDefinitions == null) return; var usedKeys = GetUsedFluentKeysInMap(map, emitWarning); @@ -42,7 +42,7 @@ namespace OpenRA.Mods.Common.Lint foreach (var context in usedKeys.EmptyKeyContexts) emitWarning($"Empty key in map ftl files required by {context}"); - var mapTranslations = FieldLoader.GetValue("value", map.TranslationDefinitions.Value); + var mapTranslations = FieldLoader.GetValue("value", map.FluentMessageDefinitions.Value); var allModTranslations = modData.Manifest.Translations; foreach (var language in GetModLanguages(allModTranslations)) diff --git a/OpenRA.Mods.Common/Lint/CheckFluentSyntax.cs b/OpenRA.Mods.Common/Lint/CheckFluentSyntax.cs index d6e6356dab..b71d4a025d 100644 --- a/OpenRA.Mods.Common/Lint/CheckFluentSyntax.cs +++ b/OpenRA.Mods.Common/Lint/CheckFluentSyntax.cs @@ -22,10 +22,10 @@ namespace OpenRA.Mods.Common.Lint { void ILintMapPass.Run(Action emitError, Action emitWarning, ModData modData, Map map) { - if (map.TranslationDefinitions == null) + if (map.FluentMessageDefinitions == null) return; - Run(emitError, emitWarning, map, FieldLoader.GetValue("value", map.TranslationDefinitions.Value)); + Run(emitError, emitWarning, map, FieldLoader.GetValue("value", map.FluentMessageDefinitions.Value)); } void ILintPass.Run(Action emitError, Action emitWarning, ModData modData)